package com.dhcc.sds.busi.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.dhcc.cdc.busi.entity.CdcEpisodeEntity;
import com.dhcc.cdc.busi.service.ICdcEpisodeService;
import com.dhcc.cdc.sys.cache.config.CdcConfigCache;
import com.dhcc.core.config.properties.SysProperties;
import com.dhcc.core.framework.util.CommonUtil;
import com.dhcc.core.framework.util.DateUtil;
import com.dhcc.core.framework.util.RedisUtil;
import com.dhcc.core.framework.util.codec.EncodeUtil;
import com.dhcc.sds.base.cache.formitem.FormItemCache;
import com.dhcc.sds.base.cache.qcentity.QcEntityCache;
import com.dhcc.sds.base.dao.SdsCommonMapper;
import com.dhcc.sds.base.dao.SdsIndexFieldMapper;
import com.dhcc.sds.base.dao.SdsIndexHeaderMapper;
import com.dhcc.sds.base.dao.SdsQcentityMapper;
import com.dhcc.sds.base.entity.SdsIndexFieldEntity;
import com.dhcc.sds.base.entity.SdsIndexHeaderEntity;
import com.dhcc.sds.base.entity.SdsQcentityEntity;
import com.dhcc.sds.base.entity.SdsQcformItemEntity;
import com.dhcc.sds.base.service.ISdsQcentityService;
import com.dhcc.sds.busi.dao.AnalysisSdsMstaMapper;
import com.dhcc.sds.busi.dao.SdsQcincaseDataMapper;
import com.dhcc.sds.busi.dao.SdsQcincaseMapper;
import com.dhcc.sds.busi.dto.AnalysisSdsMstaDto;
import com.dhcc.sds.busi.entity.SdsDimDataEntity;
import com.dhcc.sds.busi.entity.SdsQcfitemExecresultEntity;
import com.dhcc.sds.busi.service.*;
import com.dhcc.sds.busi.vo.AnalysisSdsPortalVo;
import com.dhcc.sds.util.*;
import freemarker.template.TemplateException;
import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Decoder;

import javax.annotation.Resource;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.awt.*;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description: 导出分析报告
 * @File Name: AnalysisReportService
 * @author: zhangdc
 * @date: 2022年10月11日 上午09时39分00秒
 */
@Service("analysisReportService")
public class AnalysisReportServiceImpl implements IAnalysisReportService {

    @Autowired
    private SysProperties sysPro;
    @Autowired
    private ICdcEpisodeService cdcEpisodeService;
    @Autowired
    private ISdsQcincaseService sdsQcincaseService;
    @Value("${sys.hospitalName}") //医院名称
    private String hospitalName;
    @Resource
    private SdsQcentityMapper sdsQcentityMapper;
    @Resource
    private SdsQcincaseMapper sdsQcincaseMapper;
    @Autowired
    private IAnalysisSdsPortalService analysisSdsPortalService;
    @Autowired
    private ISdsDimDataService sdsDimDataService;
    @Autowired
    private ISdsQcincaseDataService sdsQcincaseDataService;
    @Autowired
    private SdsQcincaseDataMapper sdsQcincaseDataMapper;
    @Resource
    private SdsCommonMapper sdsCommonMapper;
    @Resource
    private AnalysisSdsMstaMapper analysisSdsMstaMapper;
    @Autowired
    private ISdsQcentityService sdsQcentityService;
    @Autowired
    private SdsIndexHeaderMapper sdsIndexHeaderMapper;
    @Autowired
    private SdsIndexFieldMapper sdsIndexFieldMapper;
    @Autowired
    private ISdsQcfitemExecresultService sdsQcfitemExecresultService;
    @Autowired
    private RedisUtil redisUtil;

    private static final DecimalFormat DF = new DecimalFormat("0.00");

    /**
     * 小括号及其里面内容
     */
    private static String p1 = "\\(.*?\\)";
    /**
     * 中括号及其里面内容
     */
    private static String p2 = "\\[.*?\\]";
    /**
     * 大括号及其里面内容
     */
    private static String p3 = "\\{.*?\\}";

    private static final String BASE64_PREFIX = "base64,";

    double all = 1;
    Double cur = (double) 0;


    @Override
    public String creatReport(Map<String, Object> params) throws Exception {
        //报告类型
        String reportType = params.get("reportType").toString();
        //开始时间
        String startDate = params.get("startDate").toString();
        //结束时间
        String endDate = params.get("endDate").toString();
        //分析报告数据
        Map<String, Object> dataMap = new HashMap<String, Object>();
        //模板路径
        String templatePath = sysPro.getStaticPath() + "file_getReport/";
        //模板名称
        String templateName = "";
        //文件路径
        String filePath = sysPro.getStaticPath() + "file_getReport/reportFiles";
        //文件名称
        String fileName = "";
        String office = params.get("office").toString();
        String depart = params.get("depart").toString();
        String reportDate = this.getDateStr(startDate, 4, 0);


        switch (reportType) {
            case "1":
                //周报

                break;
            case "2":
                //月报
                break;
            case "4":
                //季报
                //年报
                templateName = "quarterReportFormwork.ftl";
                fileName = "单病种质量分析报告_季报(" + startDate.substring(0, 4) + "年第"+ params.get("quarter").toString()+"季度).doc";
                dataMap = this.getQuarterReportData(params);
                break;
            case "3":
                //年报
                templateName = "yearReportFormwork.ftl";
                fileName = "单病种质量分析报告_年报(" + startDate.substring(0, 4) + ").doc";
                dataMap = this.getYearReportData(params);
                break;
            default:
                break;
        }

        //处理redis获取图片key
        String redisKey = office + depart + reportType + reportDate;
        if (CommonUtil.isNotEmpty(params.get("quarter"))) {
            redisKey += params.get("quarter").toString();
        }
        Boolean aBoolean = redisUtil.hasKey(redisKey);
        if (aBoolean) {
            String s = redisUtil.get(redisKey);
            List<String> res = (List<String>) JSON.parse(s);
            switch (reportType) {
                case "1":
                    break;
                case "2":
                    break;
                case "3":
                    dataMap.put("recentFiveYearImg", res.get(0));
                    dataMap.put("recentYearImg", res.get(1));
                    dataMap.put("recentYearUpEntityImg", res.get(2));
                    dataMap.put("recentYearUpLocImg", res.get(3));
                    dataMap.put("recentYearRatioImg", res.get(4));
                    dataMap.put("recentYearUseTimeImg", res.get(5));
                    dataMap.put("in10DaysReportedLocDataTop5Img", res.get(6));
                    dataMap.put("over10DaysNotReportedLocDataTop5Img", res.get(7));
                    dataMap.put("notReportedLocDataTop5Img", res.get(8));
                    break;
                case "4":
                    dataMap.put("recentQuarterImg", res.get(0));
                    dataMap.put("recentQuarterUpEntityImg", res.get(1));
                    dataMap.put("recentQuarterUpLocImg", res.get(2));
                    dataMap.put("recentQuarterRatioImg", res.get(3));
                    dataMap.put("recentQuarterUseTimeImg", res.get(4));
                    dataMap.put("in10DaysReportedLocDataTop5Img", res.get(5));
                    dataMap.put("over10DaysNotReportedLocDataTop5Img", res.get(6));
                    dataMap.put("notReportedLocDataTop5Img", res.get(7));
                    break;
                default:
                    break;
            }
        } else {
            switch (reportType) {
                case "1":
                    break;
                case "2":
                    break;
                case "3":
                    processImageData(params, redisKey, dataMap, redisUtil,
                            "recentFiveYearImg", "recentYearImg", "recentYearUpEntityImg", "recentYearUpLocImg", "recentYearRatioImg",
                            "recentYearUseTimeImg", "in10DaysReportedLocDataTop5Img", "over10DaysNotReportedLocDataTop5Img", "notReportedLocDataTop5Img");
                    break;
                case "4":
                    processImageData(params, redisKey, dataMap, redisUtil,
                            "recentQuarterImg", "recentQuarterUpEntityImg", "recentQuarterUpLocImg", "recentQuarterRatioImg",
                            "recentQuarterUseTimeImg", "in10DaysReportedLocDataTop5Img", "over10DaysNotReportedLocDataTop5Img", "notReportedLocDataTop5Img");
                    break;
                default:
                    break;
            }
        }

        /** 生成word */
        WordUtil.createWord(dataMap, templatePath, templateName, filePath, fileName);

        return fileName;
    }

    /**
     * 处理图像数据的函数。
     *
     * @param params 包含参数名和值的映射，用于获取图像数据。
     * @param redisKey 用于在Redis中存储结果的键。
     * @param dataMap 用于更新图像数据的映射。
     * @param redisUtil Redis工具类，用于操作Redis。
     * @param paramNames 需要处理的参数名称数组。
     *
     * 此函数从params中获取指定的参数值，处理这些值（比如将空格替换为加号，分割字符串），然后将处理后的结果存储到Redis中，并更新dataMap。
     * 主要步骤包括遍历参数名、处理每个参数的值、将处理结果存储到Redis和更新dataMap。
     */
    private void processImageData(Map<String, Object> params, String redisKey, Map<String, Object> dataMap, RedisUtil redisUtil,
                                  String... paramNames) {
        List<String> res = new ArrayList<>();
        for (String paramName : paramNames) {
            String paramValue = params.get(paramName).toString();
            if (paramValue == null) {
                continue;
            }
            // 将参数值中的空格替换为加号，便于后续处理
            String newImageInfo = paramValue.replaceAll(" ", "+");
            // 根据BASE64_PREFIX分割处理后的参数值，提取图像信息
            String[] arr = newImageInfo.split(BASE64_PREFIX);
            if (arr.length > 1) {
                res.add(arr[1]);
            }
        }
        // 将处理结果序列化为JSON，并存储到Redis中
        redisUtil.set(redisKey, JSON.toJSONString(res));
        // 更新dataMap，将处理后的图像数据与其对应的参数名关联
        for (int i = 0; i < paramNames.length; i++) {
            String paramName = paramNames[i];
            String imgData = res.get(i);
            dataMap.put(paramName, imgData);
        }
    }

    @Override
    public Map<String, Object> getExportProcess() {
        Map<String, Object> state = new HashMap<String, Object>();
        if (all == 0) {//没有获取到数据
            state.put("v", 100);//值
            state.put("i", "none");//信息
        } else {
            if (cur < all) {//进行中
                state.put("v", (double) Math.round(cur / all * 100));//值
                state.put("i", "doing");//信息
            } else {
                state.put("v", 100);//值
                state.put("i", "done");//信息
            }
        }
        return state;
    }

    @Override
    public Map<String, Object> selectImgDataByRedis(Map<String, Object> params) {
        Map<String, Object> map = new HashMap<>();
        //报告类型
        String reportType = params.get("reportType").toString();
        //开始时间
        String startDate = params.get("startDate").toString();
        //结束时间
        String endDate = params.get("endDate").toString();
        String office = params.get("office").toString();
        String depart = params.get("depart").toString();
        String reportDate = this.getDateStr(startDate, 4, 0);
        if (CommonUtil.isNotEmpty(params.get("quarter"))) {
            reportDate += params.get("quarter");
        }
        //处理redis获取图片key
        String redisKey = office + depart + reportType + reportDate;
        Boolean aBoolean = redisUtil.hasKey(redisKey);
        if (aBoolean) {
            map.put("code", 1);
        } else {
            map.put("code", 2);
        }
        return map;
    }

    @Override
    public JSONObject selectYearImgData(Map<String, Object> params) {
        String office = params.get("office").toString();
        String depart = params.get("depart").toString();
        String reportType = params.get("reportType").toString();
        String startDate = (String) params.get("startDate");
        String endDate = (String) params.get("endDate");


        JSONObject caseObj = new JSONObject();
        //近五年上报情况
        //已完成上报病例
        Map map = new HashMap();
        map.put("state", "Up");
        map.put("office", office);
        map.put("startDate", startDate);
        map.put("endDate", endDate);
        map.put("searchType", "dish");
        int incaseUpNum = sdsQcincaseMapper.getMrlistOfDeptCount(map);
        //上一年上报
        Date start = DateUtil.parseTime(startDate);
        int currentYear = cn.hutool.core.date.DateUtil.year(start);
        String lastStartYear = (currentYear - 1) + "-01-01 00:00:00";
        String lastEndYear = (currentYear - 1) + "-12-31 23:59:59";
        map.put("startDate", lastStartYear);
        map.put("endDate", lastEndYear);
        int incaseLastUpNum = sdsQcincaseMapper.getMrlistOfDeptCount(map);

        List<AnalysisSdsPortalVo> analysisSdsPortalVoList1 = new ArrayList<>();
        AnalysisSdsPortalVo analysisSdsPortalVo1 = new AnalysisSdsPortalVo();
        analysisSdsPortalVo1.setDescription(String.valueOf(currentYear - 1));
        analysisSdsPortalVo1.setCount(incaseLastUpNum);
        AnalysisSdsPortalVo analysisSdsPortalVo2 = new AnalysisSdsPortalVo();
        analysisSdsPortalVo2.setDescription(String.valueOf(currentYear));
        analysisSdsPortalVo2.setCount(incaseUpNum);
        analysisSdsPortalVoList1.add(analysisSdsPortalVo1);
        analysisSdsPortalVoList1.add(analysisSdsPortalVo2);
        //近一年上报情况
        int endMonthCnt = currentYear * 100 + 12;
        int startMonthCnt = currentYear * 100 + 01;
        List<SdsDimDataEntity> list = sdsDimDataService.selectNearYearRep(startMonthCnt, endMonthCnt, "Up", "UpLoadDate", office);
        Map<String, Integer> rep = new LinkedHashMap<>();
        for (SdsDimDataEntity sdsDimDataEntity : list) {
            String key = sdsDimDataEntity.getDimYear() + "年" + sdsDimDataEntity.getDimMonth() + "月";
            if (StringUtils.isEmpty(rep.get(key))) {
                rep.put(key, sdsDimDataEntity.getMrCount());
            } else {
                Integer value = rep.get(key);
                rep.put(key, value + sdsDimDataEntity.getMrCount());
            }
        }
        //病种上报情况
        params.put("qcTimeDimens", "year");
        List<AnalysisSdsPortalVo> upEntityList = sdsQcincaseDataService.selectQCUpLoadData(params);
        //科室上报情况
        List<AnalysisSdsPortalVo> upLocList = sdsQcincaseDataService.selectLocUpLoadData(params);
        // 科室统计：10日内填报率、超过10日未上报率、未上报人数
        List<Map<String, Object>> locIndexList = sdsQcincaseDataMapper.selectLocLoadData(params);
        //自动填报率
        List<AnalysisSdsPortalVo> ratioList = new ArrayList<>();
        List<Long> entityIds = sdsQcincaseService.selectEntity();
        for (Long entityId : entityIds) {
            //统计病种最新一条数据
            AnalysisSdsPortalVo analysisSdsPortalVo = sdsQcincaseDataService.selectARatioByTime(entityId, params);
            if (!StringUtils.isEmpty(analysisSdsPortalVo)) {
                String s = analysisSdsPortalVo.getaRatio();
                String[] split = s.split(";");
                //过滤采集率为零的病种
                if (Objects.equals("0", split[0])) {
                    continue;
                }
                String r = split[2];
                analysisSdsPortalVo.setaRatio(r.substring(0, r.length() - 1));
                ratioList.add(analysisSdsPortalVo);
            }
        }
        //填报用时
        List<AnalysisSdsPortalVo> useTimeList = new ArrayList<>();
        a:
        for (Long entityId : entityIds) {
            List<AnalysisSdsPortalVo> sdsPortalVoList = sdsQcincaseDataService.selectUseTimeByTime(entityId, params);
            if (sdsPortalVoList.isEmpty()) {
                continue a;
            }
            Long sumMin = 0l;
            String s = sdsPortalVoList.get(0).getDescription();
            String c = sdsPortalVoList.get(0).getCode();
            List<Long> useTime = new ArrayList<>();
            b:
            for (AnalysisSdsPortalVo analysisSdsPortalVo : sdsPortalVoList) {
                sumMin += analysisSdsPortalVo.getFillUseTime();
                useTime.add(analysisSdsPortalVo.getFillUseTime());
            }
            AnalysisSdsPortalVo analysisSdsPortalVo = new AnalysisSdsPortalVo();
            String avgUseTime = StrUtil.deciFormatLong(sumMin, sdsPortalVoList.size());
            analysisSdsPortalVo.setDescription(s);
            analysisSdsPortalVo.setCode(c);
            analysisSdsPortalVo.setAvgUseTime(avgUseTime);
            analysisSdsPortalVo.setUseTime(useTime);
            useTimeList.add(analysisSdsPortalVo);

        }

        caseObj.put("recentFiveYearImg", analysisSdsPortalVoList1);
        caseObj.put("recentYearImg", rep);
        caseObj.put("recentYearUpEntity", upEntityList);
        caseObj.put("recentYearUpLoc", upLocList);
        caseObj.put("recentYearLocIndex", locIndexList);
        caseObj.put("recentYearRatioData", ratioList);
        caseObj.put("recentYearUseTimeData", useTimeList);
        return caseObj;
    }

    public Map<String, Object> getYearReportData(Map<String, Object> params) throws IOException, TemplateException {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        String startDate = (String) params.get("startDate");
        String endDate = (String) params.get("endDate");
        String reportDate = this.getDateStr(startDate, 4, 0);
        String createDate = this.getDateStr(DateUtil.now(), 3, 0);
        //出院人数
        List<CdcEpisodeEntity> cdcEpisodeEntities = cdcEpisodeService.listByDate("2", startDate, endDate, params);

        int dischPatientTotal = cdcEpisodeEntities.size();
        //入组病例
        params.put("searchType", "dish");
        params.put("excludeState", "O"); // 排除条件
        int incaseNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //自动筛查
        params.put("groupStatus", "SysRec");
        int incaseSysNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //已完成上报病例
        params.remove("excludeState");
        params.remove("groupStatus");
        params.put("state", "Up");
        int incaseUpNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //上报率
        String upFormat = StrUtil.deciFormat(incaseUpNum, incaseNum);
        //手工入组
        int incaseActiveNum = incaseNum - incaseSysNum;
        //自动筛查率
        String sysFormat = StrUtil.deciFormat(incaseSysNum, incaseNum);
        //开展病种数
        List<Long> entityIds = sdsQcincaseMapper.selectEntityByTime(params);
        int entityNum = entityIds.size();
        //未开展病种数
        Wrapper<SdsQcentityEntity> entityWpr = new EntityWrapper<>();
        entityWpr.ne("is_active", 0);// 排除无效病种
        List<SdsQcentityEntity> qcentityEntities = sdsQcentityMapper.selectList(entityWpr);
        int notEntityNum = qcentityEntities.size() - entityNum;
        //病种开展率
        String entityFormat = StrUtil.deciFormat(entityNum, qcentityEntities.size());
        //上一年
        String lastReportDate = this.getDateStr(startDate, 4, -1);
        //上一年上报
        Date date = DateUtil.parseTime(startDate);
        int currentYear = cn.hutool.core.date.DateUtil.year(date);
        String lastStartYear = (currentYear - 1) + "-01-01 00:00:00";
        String lastEndYear = (currentYear - 1) + "-12-31 23:59:59";
        params.put("startDate", lastStartYear);
        params.put("endDate", lastEndYear);
        params.put("searchType", "dish");
        int incaseLastUpNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //同比:同比增长率＝（本期数－同期数）÷同期数×100%
        String yearFormat = StrUtil.deciFormat((incaseUpNum - incaseLastUpNum), incaseLastUpNum);
        //图1 base64码 近五年上报情况
        /*String recentFiveYearImg = "";
        HashMap<String, Object> datas = new HashMap<>();
        String title1 = "近五年上报情况";
        String[] categories1 = new String[] { "2022年", "2021年"};
        int[] values1 = new int[] { 54, 2 };
        datas.put("categories", JSON.toJSONString(categories1));
        datas.put("values", JSON.toJSONString(values1));
        datas.put("title", title1);
        //recentFiveYearImg = imageToBase64(this.drawLineChart("recentFiveYearImg", recentFiveYearData));//图1
        recentFiveYearImg = this.drawEChart(datas);*/
        // 近两年上报情况表格数据
        List<Map<String, Object>> list1 = new ArrayList<>();

        Map<String, Object> map11 = new HashMap<>();
        map11.put("upYear", lastReportDate);
        map11.put("upNum", incaseLastUpNum);
        Map<String, Object> map22 = new HashMap<>();
        map22.put("upYear", reportDate);
        map22.put("upNum", incaseUpNum);
        list1.add(map11);
        list1.add(map22);

        params.put("year", currentYear);
        List<SdsDimDataEntity> monthDimData = sdsDimDataService.getUpMonth(params);
        int maxMonth = 0;
        //上报
        int maxMonthUpNmu = 0;
        //上报病例最少的月
        int minMonth = 0;
        //上报
        int minMonthUpNmu = 0;
        String avergeByMonth = "0";
        //月均上报例数
        List<Map<String, Object>> list2 = new ArrayList<>();
        int upMonthSum = 0;
        if (CommonUtil.isNotEmpty(monthDimData)) {
            List<SdsDimDataEntity> sortedMonthDimData = monthDimData.stream().sorted(Comparator.comparing(SdsDimDataEntity::getMrCount)).collect(Collectors.toList());
            //上报病例最多的月
            SdsDimDataEntity maxDimData = sortedMonthDimData.get(sortedMonthDimData.size() - 1);
            maxMonth = maxDimData.getDimMonth();
            //上报
            maxMonthUpNmu = maxDimData.getMrCount();
            //上报病例最少的月
            SdsDimDataEntity minDimData = sortedMonthDimData.get(0);
            minMonth = minDimData.getDimMonth();
            //上报
            minMonthUpNmu = minDimData.getMrCount();
            //月均上报例数
            upMonthSum = monthDimData.stream().mapToInt(SdsDimDataEntity::getMrCount).sum();
            avergeByMonth = StrUtil.deciFormatU(upMonthSum, monthDimData.size());
            for (SdsDimDataEntity sdsDimDataEntity : monthDimData) {
                Map<String, Object> map1 = new HashMap<>();
                String key = currentYear + String.format("%02d", sdsDimDataEntity.getDimMonth());
                map1.put("upYear", key);
                map1.put("upNum", sdsDimDataEntity.getMrCount());
                list2.add(map1);
            }
            list2 = list2.stream().sorted(Comparator.comparing(o -> o.get("upYear").toString())).collect(Collectors.toList());
        }


        params.put("startDate", startDate);
        params.put("endDate", endDate);
        params.put("qcTimeDimens", "year");
        List<AnalysisSdsPortalVo> upEntityList = sdsQcincaseDataService.selectQCUpLoadData(params);
        String upMaxEntityName = "";
        //上报病例最多的病种例数
        int upMaxEntityNameNum = 0;
        //上报病例最少的病种
        String upMinEntityName = "";
        //上报病例最少的病种例数
        int upMinEntityNameNum = 0;
        if (CommonUtil.isNotEmpty(upEntityList)) {
            //上报病例最多的病种
            List<AnalysisSdsPortalVo> sortedUpEntity = upEntityList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getCount)).collect(Collectors.toList());
            AnalysisSdsPortalVo maxUpEntity = sortedUpEntity.get(sortedUpEntity.size() - 1);
            upMaxEntityName = maxUpEntity.getDescription();
            //上报病例最多的病种例数
            upMaxEntityNameNum = maxUpEntity.getCount();
            //上报病例最少的病种
            AnalysisSdsPortalVo minUpEntity = sortedUpEntity.get(0);
            upMinEntityName = minUpEntity.getDescription();
            //上报病例最少的病种例数
            upMinEntityNameNum = minUpEntity.getCount();
        }

        //上报科室
        List<AnalysisSdsPortalVo> upLocList = sdsQcincaseDataService.selectLocUpLoadData(params);
        int upLocNum = upLocList.size();
        String upLocName = "";
        //上报病例最多科室
        String upMaxLocName = "";
        //上报病例最多科室例数
        int upMaxLocNum = 0;
        //上报病例数最少的科室
        String upMinLocName = "";
        //上报病例最少科室例数
        int upMinLocNum = 0;
        if (CommonUtil.isNotEmpty(upLocList)) {
            //前五的科室
            List<AnalysisSdsPortalVo> sortedUpLocList = upLocList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getCount).reversed()).collect(Collectors.toList());
            int i = 0;
            for (AnalysisSdsPortalVo analysisSdsPortalVo : sortedUpLocList) {
                i++;
                if (i > 5) break;
                upLocName += analysisSdsPortalVo.getDescription() + "、";
            }
            //上报病例最多科室
            upMaxLocName = sortedUpLocList.get(0).getDescription();
            //上报病例最多科室例数
            upMaxLocNum = sortedUpLocList.get(0).getCount();
            //上报病例数最少的科室
            upMinLocName = sortedUpLocList.get(sortedUpLocList.size() - 1).getDescription();
            //上报病例最少科室例数
            upMinLocNum = sortedUpLocList.get(sortedUpLocList.size() - 1).getCount();
        }

        // 10日内填报率前五的科室名称
        String in10DaysReportedLocNameTop5 = "";
        // 10日内填报率前五的科室数据
        String in10DaysReportedLocDataTop5 = "";
        // 超过10日未上报率前五的科室名称
        String over10DaysNotReportedLocNameTop5 = "";
        // 超过10日未上报率前五的科室数据
        String over10DaysNotReportedLocDataTop5 = "";
        // 未上报人数前五的科室名称
        String notReportedLocNameTop5 = "";
        // 未上报人数前五的科室数据
        String notReportedLocDataTop5 = "";

        // 科室统计：10日内填报率、超过10日未上报率、未上报人数
        List<Map<String, Object>> locIndexList = sdsQcincaseDataMapper.selectLocLoadData(params);
        if (CommonUtil.isNotEmpty(locIndexList)) {
            // 10日内填报率前五的科室
            List<Map<String, Object>> sortedLocIndexList = locIndexList.stream().sorted(Comparator.comparing(o -> new BigDecimal(o.get("in10DaysReportedRate").toString()))).collect(Collectors.toList());
            for (int i = 1; i <= sortedLocIndexList.size(); i++) {
                if (i > 5) {
                    break;
                }
                in10DaysReportedLocNameTop5 += sortedLocIndexList.get(sortedLocIndexList.size() - i).get("locName").toString() + "、";
                in10DaysReportedLocDataTop5 += sortedLocIndexList.get(sortedLocIndexList.size() - i).get("in10DaysReportedRate").toString() + "%、";
            }
            // 10日内未上报率前五的科室
            List<Map<String, Object>> sortedLocIndexList1 = locIndexList.stream().sorted(Comparator.comparing(o -> new BigDecimal(o.get("over10DaysNotReportedRate").toString()))).collect(Collectors.toList());
            for (int i = 1; i <= sortedLocIndexList1.size(); i++) {
                if (i > 5) {
                    break;
                }
                over10DaysNotReportedLocNameTop5 += sortedLocIndexList1.get(sortedLocIndexList1.size() - i).get("locName").toString() + "、";
                over10DaysNotReportedLocDataTop5 += sortedLocIndexList1.get(sortedLocIndexList1.size() - i).get("over10DaysNotReportedRate").toString() + "%、";
            }
            // 未上报人数前五的科室
            List<Map<String, Object>> sortedLocIndexList2 = locIndexList.stream().sorted(Comparator.comparing(o -> new BigDecimal(o.get("notReportedCount").toString()))).collect(Collectors.toList());
            for (int i = 1; i <= sortedLocIndexList2.size(); i++) {
                if (i > 5) {
                    break;
                }
                notReportedLocNameTop5 += sortedLocIndexList2.get(sortedLocIndexList2.size() - i).get("locName").toString() + "、";
                notReportedLocDataTop5 += sortedLocIndexList2.get(sortedLocIndexList2.size() - i).get("notReportedCount").toString() + "、";
            }
        }

        params.put("startDate", startDate);
        params.put("endDate", endDate);
        List<AnalysisSdsMstaDto> statisList = analysisSdsMstaMapper.selectMstaDataByEntity(params);
        statisList.remove(statisList.size() - 1);//查询结果有合计行，需要删除合计行
        for (AnalysisSdsMstaDto analysisSdsMstaDto : statisList) {
            Long entityId = analysisSdsMstaDto.getEntityId();
            if (CommonUtil.isEmpty(entityId)) {
                continue;
            }
            SdsQcentityEntity sdsQcentityEntity = sdsQcentityService.selectById(entityId);
            analysisSdsMstaDto.setEntityDesc(sdsQcentityEntity.getBtDesc());
            Integer hosDays = analysisSdsMstaDto.getHosDays();
            Float hosCost = analysisSdsMstaDto.getHosCost();
            Float consumCost1 = analysisSdsMstaDto.getConsumCost1();
            Float consumCost2 = analysisSdsMstaDto.getConsumCost2();
            Float consumCost3 = analysisSdsMstaDto.getConsumCost3();
            Float consumCost4 = analysisSdsMstaDto.getConsumCost4();
            Float consumCost = consumCost1 + consumCost2 + consumCost3;
            analysisSdsMstaDto.setConsumCost(consumCost);
            Float medeCost = analysisSdsMstaDto.getMedeCost();
            Integer consistentNum = analysisSdsMstaDto.getConsistentNum();
            BigDecimal decimalconsistentNum = new BigDecimal(consistentNum);
            if (!Objects.equals(0, consistentNum)) {
                DecimalFormat df = new DecimalFormat("0.00");
                String averageHosDays = df.format((float) hosDays / consistentNum);
                String averageHosCost = df.format(hosCost / consistentNum);
                String averageMedeCost = df.format(medeCost / consistentNum);
                String averageConsumCost = df.format(consumCost / consistentNum);
                BigDecimal decimalDeathNum = new BigDecimal(analysisSdsMstaDto.getDeathNum());
                Double r = decimalDeathNum.divide(decimalconsistentNum, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).doubleValue();
                analysisSdsMstaDto.setAverageHosDays(averageHosDays);
                analysisSdsMstaDto.setAverageHosCost(averageHosCost);
                analysisSdsMstaDto.setAverageMedeCost(averageMedeCost);
                analysisSdsMstaDto.setAverageConsumCost(averageConsumCost);
                analysisSdsMstaDto.setAverageDeathNumRate(Double.toString(r));
            }
        }


        String avgMaxFeeEntityName = "";
        //次均住院费用最高
        String avgMaxFee = "";
        //次均住院费用最低病种
        String avgMinFeeEntityName = "";
        //次均住院费用最低
        String avgMinFee = "";
        String avgMaxDayEntityName = "";
        //次均住院日最高
        String avgMaxDay = "";
        //次均住院日最低病种
        String avgMinDayEntityName = "";
        //次均住院日最低
        String avgMinDay = "";
        String deadFirstEntityName = "";
        //病死率最高病死率
        String deadFirstFormat = "";
        //病死率第二高
        String deadSecEntityName = "";
        //病死率第二高病死率
        String deadSecFormat = "";
        //病死率第三高
        String deadThirdEntityName = "";
        //病死率第三高病死率
        String deadThirdFormat = "";
        String avgMaxMedeCostEntityName = "";
        String avgMaxMedeCost = "";
        String avgMinMedeCostEntityName = "";
        String avgMinMedeCost = "";
        String avgMaxConsumCostEntityName = "";
        String avgMaxConsumCost = "";
        String avgMinConsumCostEntityName = "";
        String avgMinConsumCost = "";
        if (CommonUtil.isNotEmpty(statisList)) {
            //次均住院费用最高病种
            List<AnalysisSdsMstaDto> sortedHospFee = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageHosCost, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            )).collect(Collectors.toList());
            for (int i = 0; i < sortedHospFee.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxFeeEntityName += sortedHospFee.get(sortedHospFee.size() - (i + 1)).getEntityDesc() + "、";
                //次均住院费用最高
                avgMaxFee += sortedHospFee.get(sortedHospFee.size() - (i + 1)).getAverageHosCost() + "、";
                //次均住院费用最低病种
                avgMinFeeEntityName += sortedHospFee.get(i).getEntityDesc() + "、";
                //次均住院费用最低
                avgMinFee += sortedHospFee.get(i).getAverageHosCost() + "、";
            }


            //次均住院日最高病种
            List<AnalysisSdsMstaDto> sortedHospDay = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageHosDays, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            )).collect(Collectors.toList());
            for (int i = 0; i < sortedHospDay.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxDayEntityName += sortedHospDay.get(sortedHospDay.size() - (i + 1)).getEntityDesc() + "、";
                //次均住院日最高
                avgMaxDay += sortedHospDay.get(sortedHospDay.size() - (i + 1)).getAverageHosDays() + "、";
                //次均住院日最低病种
                avgMinDayEntityName += sortedHospDay.get(i).getEntityDesc() + "、";
                //次均住院日最低
                avgMinDay += sortedHospDay.get(i).getAverageHosDays() + "、";
            }

            //病死率最高
            List<AnalysisSdsMstaDto> sortedAverageDeathNumRate = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageDeathNumRate, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            ).reversed()).collect(Collectors.toList());

            deadFirstEntityName = sortedAverageDeathNumRate.get(0).getEntityDesc();
            //病死率最高病死率
            deadFirstFormat = sortedAverageDeathNumRate.get(0).getAverageDeathNumRate();
            //病死率第二高
            deadSecEntityName = sortedAverageDeathNumRate.get(1).getEntityDesc();
            //病死率第二高病死率
            deadSecFormat = sortedAverageDeathNumRate.get(1).getAverageDeathNumRate();
            //病死率第三高
            deadThirdEntityName = sortedAverageDeathNumRate.get(2).getEntityDesc();
            //病死率第三高病死率
            deadThirdFormat = sortedAverageDeathNumRate.get(2).getAverageDeathNumRate();
            //平均药费
            List<AnalysisSdsMstaDto> sortedMedeCost = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageMedeCost, (x, y) -> {
                BigDecimal bigDecimalA = new BigDecimal(x);
                BigDecimal bigDecimalB = new BigDecimal(y);
                return bigDecimalA.compareTo(bigDecimalB);
            })).collect(Collectors.toList());
            for (int i = 0; i < sortedMedeCost.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxMedeCostEntityName += sortedMedeCost.get(sortedMedeCost.size() - (i + 1)).getEntityDesc() + "、";
                avgMaxMedeCost += sortedMedeCost.get(sortedMedeCost.size() - (i + 1)).getAverageMedeCost() + "、";
                avgMinMedeCostEntityName += sortedMedeCost.get(i).getEntityDesc() + "、";
                avgMinMedeCost += sortedMedeCost.get(i).getAverageMedeCost() + "、";
            }

            //平均耗材费
            List<AnalysisSdsMstaDto> sortedAverageConsumCost = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageConsumCost, (x, y) -> {
                BigDecimal bigDecimalA = new BigDecimal(x);
                BigDecimal bigDecimalB = new BigDecimal(y);
                return bigDecimalA.compareTo(bigDecimalB);
            })).collect(Collectors.toList());
            for (int i = 0; i < sortedAverageConsumCost.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxConsumCostEntityName += sortedAverageConsumCost.get(sortedAverageConsumCost.size() - (i + 1)).getEntityDesc() + "、";
                avgMaxConsumCost += sortedAverageConsumCost.get(sortedAverageConsumCost.size() - (i + 1)).getAverageConsumCost() + "、";
                avgMinConsumCostEntityName += sortedAverageConsumCost.get(i).getEntityDesc() + "、";
                avgMinConsumCost += sortedAverageConsumCost.get(i).getAverageConsumCost() + "、";
            }
        }

        // 费用和住院日增幅、降幅数据处理
        // 费用map
        Map<String, BigDecimal[]> diseaseCosts = new HashMap<>();
        // 住院日map
        Map<String, BigDecimal[]> diseaseUseTime = new HashMap<>();
        // 当前选择年的数据
        for (AnalysisSdsMstaDto cost : statisList) {
            BigDecimal consistentNum = BigDecimal.valueOf(cost.getConsistentNum());
            Long entityId = cost.getEntityId();
            String entityName = QcEntityCache.me().getQcEntityById(entityId).getBtDesc();
            diseaseCosts.putIfAbsent(entityName, new BigDecimal[2]);
            diseaseCosts.get(entityName)[0] = BigDecimal.valueOf(cost.getHosCost()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
            diseaseUseTime.putIfAbsent(entityName, new BigDecimal[2]);
            diseaseUseTime.get(entityName)[0] = BigDecimal.valueOf(cost.getHosDays()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
        }
        // 前一年的统计数据
        Map<String, Object> lastParams = new HashMap<>();
        lastParams.putAll(params);
        lastParams.put("startDate", lastStartYear);
        lastParams.put("endDate", lastEndYear);
        List<AnalysisSdsMstaDto> lastYearStatisList = analysisSdsMstaMapper.selectMstaDataByEntity(lastParams);
        for (AnalysisSdsMstaDto cost : lastYearStatisList) {
            BigDecimal consistentNum = BigDecimal.valueOf(cost.getConsistentNum());
            Long entityId = cost.getEntityId();
            String entityName = QcEntityCache.me().getQcEntityById(entityId).getBtDesc();
            if (diseaseCosts.get(entityName)!=null) {
                diseaseCosts.get(entityName)[1] = BigDecimal.valueOf(cost.getHosCost()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
            }
            if (diseaseUseTime.get(entityName)!=null) {
                diseaseUseTime.get(entityName)[1] = BigDecimal.valueOf(cost.getHosDays()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
            }
        }

        // 费用增幅、降幅
        List<Map<String, Object>> costRatioList = new ArrayList<>();
        for (Map.Entry<String, BigDecimal[]> entry : diseaseCosts.entrySet()) {
            Map<String, Object> costRatioMap = new HashMap<>();
            // 处理某一年没有某个病种的情况，将缺失的费用默认为没有变化
            if (entry.getValue()[0] == null) {
                entry.getValue()[0] = BigDecimal.valueOf(0);
            } else if (entry.getValue()[1] == null) {
                entry.getValue()[1] = BigDecimal.valueOf(0);
            }

            costRatioMap.put("entityName", entry.getKey());
            costRatioMap.put("lastYearData", entry.getValue()[1]);
            costRatioMap.put("thisYearData", entry.getValue()[0]);
            // 使用BigDecimal计算成本比率，以保留精度并避免科学计数法
            if (entry.getValue()[1].compareTo(BigDecimal.valueOf(0)) == 0) {
                costRatioMap.put("costRatio", BigDecimal.valueOf(0));
            } else {
                BigDecimal costRatioValue = entry.getValue()[0]
                        .subtract(entry.getValue()[1])
                        .divide(entry.getValue()[1], 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                costRatioMap.put("costRatio", costRatioValue);
            }

            costRatioList.add(costRatioMap);
        }
        // 费用按照降幅排序
        costRatioList.sort(Comparator.comparing(map -> (BigDecimal) map.get("costRatio")));

        // 住院日增幅、降幅
        List<Map<String, Object>> useTimeRatioList = new ArrayList<>();
        for (Map.Entry<String, BigDecimal[]> entry : diseaseUseTime.entrySet()) {
            Map<String, Object> useTimeRatioMap = new HashMap<>();
            // 处理某一年没有某个病种的情况，将缺失的住院日默认为没有变化
            BigDecimal[] values = entry.getValue();
            if (values[0] == null) {
                values[0] = BigDecimal.valueOf(0);
            }
            if (values[1] == null) {
                values[1] = BigDecimal.valueOf(0);
            }

            useTimeRatioMap.put("entityName", entry.getKey());
            useTimeRatioMap.put("lastYearData", entry.getValue()[1]);
            useTimeRatioMap.put("thisYearData", entry.getValue()[0]);
            // 使用BigDecimal计算成本比率，以保留精度并避免科学计数法
            if (entry.getValue()[1].compareTo(BigDecimal.valueOf(0)) == 0) {
                useTimeRatioMap.put("useTimeRatio", BigDecimal.valueOf(0));
            } else {
                BigDecimal useTimeRatioValue = entry.getValue()[0]
                        .subtract(entry.getValue()[1])
                        .divide(entry.getValue()[1], 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                useTimeRatioMap.put("useTimeRatio", useTimeRatioValue);
            }

            useTimeRatioList.add(useTimeRatioMap);
        }
        // 住院日按照降幅排序
        useTimeRatioList.sort(Comparator.comparing(map -> (BigDecimal) map.get("useTimeRatio")));

        // 费用降幅最大5个病种
        String costRatioMaxEntityName = "";
        // 费用降幅最大5个病种降幅
        String costRatioMax = "";
        // 费用增幅最大5个病种
        String costRatioMinEntityName = "";
        // 费用增幅最大5个病种增幅
        String costRatioMin = "";
        for (int i = 0; i < costRatioList.size(); i++) {
            if (i >= 5) {
                break;
            }
            costRatioMaxEntityName += costRatioList.get(i).get("entityName") + "、";
            costRatioMax += costRatioList.get(i).get("costRatio") + "、";
            costRatioMinEntityName += costRatioList.get(costRatioList.size() - (i + 1)).get("entityName") + "、";
            costRatioMin += costRatioList.get(costRatioList.size() - (i + 1)).get("costRatio") + "、";
        }

        // 住院日降幅最大5个病种
        String useTimeRatioMaxEntityName = "";
        // 住院日降幅最大5个病种降幅
        String useTimeRatioMax = "";
        // 住院日增幅最大5个病种
        String useTimeRatioMinEntityName = "";
        // 住院日增幅最大5个病种增幅
        String useTimeRatioMin = "";
        for (int i = 0; i < useTimeRatioList.size(); i++) {
            if (i >= 5) {
                break;
            }
            useTimeRatioMaxEntityName += useTimeRatioList.get(i).get("entityName") + "、";
            useTimeRatioMax += useTimeRatioList.get(i).get("useTimeRatio") + "、";
            useTimeRatioMinEntityName += useTimeRatioList.get(useTimeRatioList.size() - (i + 1)).get("entityName") + "、";
            useTimeRatioMin += useTimeRatioList.get(useTimeRatioList.size() - (i + 1)).get("useTimeRatio") + "、";
        }

        List<AnalysisSdsPortalVo> ratioList = new ArrayList<>();
        for (Long entityId : entityIds) {
            //统计病种最新一条数据
            AnalysisSdsPortalVo analysisSdsPortalVo = sdsQcincaseDataService.selectARatioByTime(entityId, params);
            if (!StringUtils.isEmpty(analysisSdsPortalVo)) {
                String s = analysisSdsPortalVo.getaRatio();
                String[] split = s.split(";");
                //过滤采集率为零的病种
                if (Objects.equals("0", split[0])) {
                    continue;
                }
                String r = split[2];
                analysisSdsPortalVo.setaRatio(r.substring(0, r.length() - 1));
                ratioList.add(analysisSdsPortalVo);
            }
        }

        //自动采集率中位数
        String avgAutoAcq = "";
        //采集率最高的病种
        String autoAcqMaxEntityName = "";
        //采集率最高
        String autoAcqMax = "";
        //采集率最低的病种
        String autoAcqMinEntityName = "";
        //采集率最高
        String autoAcqMin = "";
        if (CommonUtil.isNotEmpty(ratioList)) {
            List<AnalysisSdsPortalVo> sortedARatio = ratioList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getaRatio, (x, y) -> {
                        BigDecimal dataA = new BigDecimal(x);
                        BigDecimal dataB = new BigDecimal(y);
                        return dataA.compareTo(dataB);
                    }
            )).collect(Collectors.toList());
            //自动采集率中位数
            avgAutoAcq = median(sortedARatio);
            for (int i = 0; i < sortedARatio.size(); i++) {
                if (i >= 10) {
                    break;
                }
                //采集率最高的病种
                autoAcqMaxEntityName += sortedARatio.get(sortedARatio.size() - (i + 1)).getCode() + "、";
                //采集率最高
                autoAcqMax += sortedARatio.get(sortedARatio.size() - (i + 1)).getaRatio() + "、";
                if (i < 5) {
                    //采集率最低的病种
                    autoAcqMinEntityName += sortedARatio.get(i).getCode() + "、";
                    //采集率最高
                    autoAcqMin += sortedARatio.get(i).getaRatio() + "、";
                }
            }

        }


        List<AnalysisSdsPortalVo> useTimeList = new ArrayList<>();
        a:
        for (Long entityId : entityIds) {
            List<AnalysisSdsPortalVo> sdsPortalVoList = sdsQcincaseDataService.selectUseTimeByTime(entityId, params);
            if (sdsPortalVoList.isEmpty()) {
                continue a;
            }
            Long sumMin = 0l;
            String s = sdsPortalVoList.get(0).getDescription();
            String c = sdsPortalVoList.get(0).getCode();
            List<Long> useTime = new ArrayList<>();
            b:
            for (AnalysisSdsPortalVo analysisSdsPortalVo : sdsPortalVoList) {
                sumMin += analysisSdsPortalVo.getFillUseTime();
                useTime.add(analysisSdsPortalVo.getFillUseTime());
            }
            AnalysisSdsPortalVo analysisSdsPortalVo = new AnalysisSdsPortalVo();
            String avgUseTime = StrUtil.deciFormatLong(sumMin, sdsPortalVoList.size());
            analysisSdsPortalVo.setDescription(s);
            analysisSdsPortalVo.setCode(c);
            analysisSdsPortalVo.setAvgUseTime(avgUseTime);
            analysisSdsPortalVo.setUseTime(useTime);
            useTimeList.add(analysisSdsPortalVo);

        }

        String avgFillingMaxEntityName = "";
        //填报平均用时最长
        String avgFillingMax = "";
        //填报平均用时最短的病种
        String avgFillingMinEntityName = "";
        //填报平均用时最短
        String avgFillingMin = "";
        if (CommonUtil.isNotEmpty(useTimeList)) {
            List<AnalysisSdsPortalVo> sortedUseTime = useTimeList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getAvgUseTime, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            )).collect(Collectors.toList());
            for (int i = 0; i < sortedUseTime.size(); i++) {
                if (i >= 10) {
                    break;
                }
                //填报平均用时最长的病种
                avgFillingMaxEntityName += sortedUseTime.get(sortedUseTime.size() - (i + 1)).getCode() + "、";
                //填报平均用时最长
                avgFillingMax += sortedUseTime.get(sortedUseTime.size() - (i + 1)).getAvgUseTime() + "、";
                if (i < 5) {
                    //填报平均用时最短的病种
                    avgFillingMinEntityName += sortedUseTime.get(i).getCode() + "、";
                    //填报平均用时最短
                    avgFillingMin += sortedUseTime.get(i).getAvgUseTime() + "、";
                }
            }
        }

        // 10大国考病种和三大重点科室14个病种报表统计（病例数、平均住院日、次均费用、病死率、并发症）
        // 10大国考病种
        List<AnalysisSdsMstaDto> nationalExamDiseaseList = this.calculateAndStoreStatistics(params, "NationalExamDisease");
        // 三大重点科室14个病种报表统计
        List<AnalysisSdsMstaDto> keyDeptDiseaseList = this.calculateAndStoreStatistics(params, "KeyDeptDisease");


        // 院内重点病种指标
        //一级指标（单病种名称）
        List<Map<String, Object>> keyStatisticsList = calculateAndStoreKeyStatistics(params);


        //ftl赋值
        dataMap.put("hospitalName", hospitalName);
        dataMap.put("reportDate", reportDate);
        dataMap.put("createDate", createDate);
        dataMap.put("dischPatientTotal", dischPatientTotal);
        dataMap.put("incaseNum", incaseNum);
        dataMap.put("incaseUpNum", incaseUpNum);
        dataMap.put("upFormat", upFormat);
        dataMap.put("incaseSysNum", incaseSysNum);
        dataMap.put("incaseActiveNum", incaseActiveNum);
        dataMap.put("sysFormat", sysFormat);
        dataMap.put("entityNum", entityNum);
        dataMap.put("notEntityNum", notEntityNum);
        dataMap.put("entityFormat", entityFormat);
        dataMap.put("lastReportDate", lastReportDate);
        dataMap.put("incaseLastUpNum", incaseLastUpNum);
        dataMap.put("yearFormat", yearFormat);
        dataMap.put("maxMonth", maxMonth);
        dataMap.put("maxMonthUpNmu", maxMonthUpNmu);
        dataMap.put("minMonth", minMonth);
        dataMap.put("minMonthUpNmu", minMonthUpNmu);
        dataMap.put("avergeByMonth", avergeByMonth);
        dataMap.put("upMaxEntityName", upMaxEntityName);
        dataMap.put("upMaxEntityNameNum", upMaxEntityNameNum);
        dataMap.put("upMinEntityName", upMinEntityName);
        dataMap.put("upMinEntityNameNum", upMinEntityNameNum);
        dataMap.put("upLocNum", upLocNum);
        dataMap.put("upLocName", upLocName);
        dataMap.put("upMaxLocName", upMaxLocName);
        dataMap.put("upMaxLocNum", upMaxLocNum);
        dataMap.put("upMinLocName", upMinLocName);
        dataMap.put("upMinLocNum", upMinLocNum);
        dataMap.put("in10DaysReportedLocNameTop5", StringUtils.trimTrailingCharacter(in10DaysReportedLocNameTop5, '、'));
        dataMap.put("in10DaysReportedLocDataTop5", StringUtils.trimTrailingCharacter(in10DaysReportedLocDataTop5, '、'));
        dataMap.put("over10DaysNotReportedLocNameTop5", StringUtils.trimTrailingCharacter(over10DaysNotReportedLocNameTop5, '、'));
        dataMap.put("over10DaysNotReportedLocDataTop5", StringUtils.trimTrailingCharacter(over10DaysNotReportedLocDataTop5, '、'));
        dataMap.put("notReportedLocNameTop5", StringUtils.trimTrailingCharacter(notReportedLocNameTop5, '、'));
        dataMap.put("notReportedLocDataTop5", StringUtils.trimTrailingCharacter(notReportedLocDataTop5, '、'));
        dataMap.put("avgMaxFeeEntityName", StringUtils.trimTrailingCharacter(avgMaxFeeEntityName, '、'));
        dataMap.put("avgMaxFee", StringUtils.trimTrailingCharacter(avgMaxFee, '、'));
        dataMap.put("avgMinFeeEntityName", StringUtils.trimTrailingCharacter(avgMinFeeEntityName, '、'));
        dataMap.put("avgMinFee", StringUtils.trimTrailingCharacter(avgMinFee, '、'));
        dataMap.put("costRatioMaxEntityName", StringUtils.trimTrailingCharacter(costRatioMaxEntityName, '、'));
        dataMap.put("costRatioMax", StringUtils.trimTrailingCharacter(costRatioMax, '、'));
        dataMap.put("costRatioMinEntityName", StringUtils.trimTrailingCharacter(costRatioMinEntityName, '、'));
        dataMap.put("costRatioMin", StringUtils.trimTrailingCharacter(costRatioMin, '、'));
        dataMap.put("costRatioList", costRatioList);
        dataMap.put("avgMaxDayEntityName", StringUtils.trimTrailingCharacter(avgMaxDayEntityName, '、'));
        dataMap.put("avgMaxDay", StringUtils.trimTrailingCharacter(avgMaxDay, '、'));
        dataMap.put("avgMinDayEntityName", StringUtils.trimTrailingCharacter(avgMinDayEntityName, '、'));
        dataMap.put("avgMinDay", StringUtils.trimTrailingCharacter(avgMinDay, '、'));
        dataMap.put("useTimeRatioMinEntityName", StringUtils.trimTrailingCharacter(useTimeRatioMinEntityName, '、'));
        dataMap.put("useTimeRatioMin", StringUtils.trimTrailingCharacter(useTimeRatioMin, '、'));
        dataMap.put("useTimeRatioMaxEntityName", StringUtils.trimTrailingCharacter(useTimeRatioMaxEntityName, '、'));
        dataMap.put("useTimeRatioMax", StringUtils.trimTrailingCharacter(useTimeRatioMax, '、'));
        dataMap.put("useTimeRatioList", useTimeRatioList);
        dataMap.put("deadFirstEntityName", deadFirstEntityName);
        dataMap.put("deadFirstFormat", deadFirstFormat);
        dataMap.put("deadSecEntityName", deadSecEntityName);
        dataMap.put("deadSecFormat", deadSecFormat);
        dataMap.put("deadThirdEntityName", deadThirdEntityName);
        dataMap.put("deadThirdFormat", deadThirdFormat);
        dataMap.put("avgAutoAcq", avgAutoAcq);
        dataMap.put("autoAcqMaxEntityName", StringUtils.trimTrailingCharacter(autoAcqMaxEntityName, '、'));
        dataMap.put("autoAcqMax", StringUtils.trimTrailingCharacter(autoAcqMax, '、'));
        dataMap.put("autoAcqMinEntityName", StringUtils.trimTrailingCharacter(autoAcqMinEntityName, '、'));
        dataMap.put("autoAcqMin", StringUtils.trimTrailingCharacter(autoAcqMin, '、'));
        dataMap.put("avgFillingMaxEntityName", StringUtils.trimTrailingCharacter(avgFillingMaxEntityName, '、'));
        dataMap.put("avgFillingMax", StringUtils.trimTrailingCharacter(avgFillingMax, '、'));
        dataMap.put("avgFillingMinEntityName", StringUtils.trimTrailingCharacter(avgFillingMinEntityName, '、'));
        dataMap.put("avgFillingMin", StringUtils.trimTrailingCharacter(avgFillingMin, '、'));
        dataMap.put("avgMaxMedeCostEntityName", StringUtils.trimTrailingCharacter(avgMaxMedeCostEntityName, '、'));
        dataMap.put("avgMaxMedeCost", StringUtils.trimTrailingCharacter(avgMaxMedeCost, '、'));
        dataMap.put("avgMinMedeCostEntityName", StringUtils.trimTrailingCharacter(avgMinMedeCostEntityName, '、'));
        dataMap.put("avgMinMedeCost", StringUtils.trimTrailingCharacter(avgMinMedeCost, '、'));
        dataMap.put("avgMaxConsumCostEntityName", StringUtils.trimTrailingCharacter(avgMaxConsumCostEntityName, '、'));
        dataMap.put("avgMaxConsumCost", StringUtils.trimTrailingCharacter(avgMaxConsumCost, '、'));
        dataMap.put("avgMinConsumCostEntityName", StringUtils.trimTrailingCharacter(avgMinConsumCostEntityName, '、'));
        dataMap.put("avgMinConsumCost", StringUtils.trimTrailingCharacter(avgMinConsumCost, '、'));
        /*dataMap.put("recentFiveYearImg", recentFiveYearImg);*/
        dataMap.put("recentFiveYearExcelData", list1);
        dataMap.put("recentYearMonthExcelData", list2);
        dataMap.put("nationalExamDiseaseList", nationalExamDiseaseList);
        dataMap.put("keyDeptDiseaseList", keyDeptDiseaseList);
        dataMap.put("keyStatisticsList", keyStatisticsList);
        return dataMap;
    }

    @Override
    public JSONObject selectQuarterImgData(Map<String, Object> params) {
        String office = params.get("office").toString();
        String depart = params.get("depart").toString();
        String reportType = params.get("reportType").toString();
        String startDate = (String) params.get("startDate");
        String endDate = (String) params.get("endDate");


        JSONObject caseObj = new JSONObject();
        //本季度各月份上报情况
        Date date = DateUtil.parseTime(startDate);
        int currentYear = cn.hutool.core.date.DateUtil.year(date);
        // 计算本季度的月份范围
        int currentQuarter = cn.hutool.core.date.DateUtil.quarter(date);
        int endMonthCnt = currentYear * 100;
        int startMonthCnt = currentYear * 100;
        switch (currentQuarter) {
            case 1:
                startMonthCnt += 1;
                endMonthCnt += 3;
                break;
            case 2:
                startMonthCnt += 4;
                endMonthCnt += 6;
                break;
            case 3:
                startMonthCnt += 7;
                endMonthCnt += 9;
                break;
            default:
                startMonthCnt += 10;
                endMonthCnt += 12;
        }
        params.put("year", currentYear);

        List<SdsDimDataEntity> list = sdsDimDataService.selectNearYearRep(startMonthCnt, endMonthCnt, "Up", "UpLoadDate", office);
        Map<String, Integer> rep = new LinkedHashMap<>();
        for (SdsDimDataEntity sdsDimDataEntity : list) {
            String key = sdsDimDataEntity.getDimYear() + "年" + sdsDimDataEntity.getDimMonth() + "月";
            if (StringUtils.isEmpty(rep.get(key))) {
                rep.put(key, sdsDimDataEntity.getMrCount());
            } else {
                Integer value = rep.get(key);
                rep.put(key, value + sdsDimDataEntity.getMrCount());
            }
        }
        //病种上报情况
        params.put("qcTimeDimens", "year");
        List<AnalysisSdsPortalVo> upEntityList = sdsQcincaseDataService.selectQCUpLoadData(params);
        //科室上报情况
        List<AnalysisSdsPortalVo> upLocList = sdsQcincaseDataService.selectLocUpLoadData(params);
        // 科室统计：10日内填报率、超过10日未上报率、未上报人数
        List<Map<String, Object>> locIndexList = sdsQcincaseDataMapper.selectLocLoadData(params);
        //自动填报率
        List<AnalysisSdsPortalVo> ratioList = new ArrayList<>();
        List<Long> entityIds = sdsQcincaseService.selectEntity();
        for (Long entityId : entityIds) {
            //统计病种最新一条数据
            AnalysisSdsPortalVo analysisSdsPortalVo = sdsQcincaseDataService.selectARatioByTime(entityId, params);
            if (!StringUtils.isEmpty(analysisSdsPortalVo)) {
                String s = analysisSdsPortalVo.getaRatio();
                String[] split = s.split(";");
                //过滤采集率为零的病种
                if (Objects.equals("0", split[0])) {
                    continue;
                }
                String r = split[2];
                analysisSdsPortalVo.setaRatio(r.substring(0, r.length() - 1));
                ratioList.add(analysisSdsPortalVo);
            }
        }
        //填报用时
        List<AnalysisSdsPortalVo> useTimeList = new ArrayList<>();
        a:
        for (Long entityId : entityIds) {
            List<AnalysisSdsPortalVo> sdsPortalVoList = sdsQcincaseDataService.selectUseTimeByTime(entityId, params);
            if (sdsPortalVoList.isEmpty()) {
                continue a;
            }
            Long sumMin = 0l;
            String s = sdsPortalVoList.get(0).getDescription();
            String c = sdsPortalVoList.get(0).getCode();
            List<Long> useTime = new ArrayList<>();
            b:
            for (AnalysisSdsPortalVo analysisSdsPortalVo : sdsPortalVoList) {
                sumMin += analysisSdsPortalVo.getFillUseTime();
                useTime.add(analysisSdsPortalVo.getFillUseTime());
            }
            AnalysisSdsPortalVo analysisSdsPortalVo = new AnalysisSdsPortalVo();
            String avgUseTime = StrUtil.deciFormatLong(sumMin, sdsPortalVoList.size());
            analysisSdsPortalVo.setDescription(s);
            analysisSdsPortalVo.setCode(c);
            analysisSdsPortalVo.setAvgUseTime(avgUseTime);
            analysisSdsPortalVo.setUseTime(useTime);
            useTimeList.add(analysisSdsPortalVo);

        }

        caseObj.put("recentQuarterImg", rep);
        caseObj.put("recentQuarterUpEntity", upEntityList);
        caseObj.put("recentQuarterUpLoc", upLocList);
        caseObj.put("recentQuarterLocIndex", locIndexList);
        caseObj.put("recentQuarterRatioData", ratioList);
        caseObj.put("recentQuarterUseTimeData", useTimeList);
        return caseObj;
    }

    private Map<String, Object> getQuarterReportData(Map<String, Object> params) {
        Map<String, Object> dataMap = new HashMap<String, Object>();
        String startDate = (String) params.get("startDate");
        String endDate = (String) params.get("endDate");
        String reportDate = this.getDateStr(startDate, 4, 0)+params.get("quarter").toString()+"季度";
        String createDate = this.getDateStr(DateUtil.now(), 3, 0);
        //出院人数
        List<CdcEpisodeEntity> cdcEpisodeEntities = cdcEpisodeService.listByDate("2", startDate, endDate, params);

        int dischPatientTotal = cdcEpisodeEntities.size();
        //入组病例
        params.put("searchType", "dish");
        params.put("excludeState", "O"); // 排除条件
        int incaseNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //自动筛查
        params.put("groupStatus", "SysRec");
        int incaseSysNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //已完成上报病例
        params.remove("excludeState");
        params.remove("groupStatus");
        params.put("state", "Up");
        int incaseUpNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //上报率
        String upFormat = StrUtil.deciFormat(incaseUpNum, incaseNum);
        //手工入组
        int incaseActiveNum = incaseNum - incaseSysNum;
        //自动筛查率
        String sysFormat = StrUtil.deciFormat(incaseSysNum, incaseNum);
        //开展病种数
        List<Long> entityIds = sdsQcincaseMapper.selectEntityByTime(params);
        int entityNum = entityIds.size();
        //未开展病种数
        Wrapper<SdsQcentityEntity> entityWpr = new EntityWrapper<>();
        entityWpr.ne("is_active", 0);// 排除无效病种
        List<SdsQcentityEntity> qcentityEntities = sdsQcentityMapper.selectList(entityWpr);
        int notEntityNum = qcentityEntities.size() - entityNum;
        //病种开展率
        String entityFormat = StrUtil.deciFormat(entityNum, qcentityEntities.size());
        //上一季度环比上报
        Date date = DateUtil.parseTime(startDate);
        // 计算上一季度的开始日期
        Date previousQuarterStart = cn.hutool.core.date.DateUtil.beginOfMonth(cn.hutool.core.date.DateUtil.offsetMonth(date, -3));
        // 计算上一季度的结束日期
        Date previousQuarterEnd = cn.hutool.core.date.DateUtil.endOfMonth(cn.hutool.core.date.DateUtil.offsetMonth(date, -1));
        // 输出日期字符串格式化为"yyyy-MM-dd"
        String previousQuarterStartStr = DateUtil.format(previousQuarterStart, "yyyy-MM-dd") + " 00:00:00";
        String previousQuarterEndStr = DateUtil.format(previousQuarterEnd, "yyyy-MM-dd") + " 23:59:59";
        params.put("startDate", previousQuarterStartStr);
        params.put("endDate", previousQuarterEndStr);
        params.put("searchType", "dish");
        int incaseLastUpNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //环比:环比增长率＝（本期数－上期数）÷上期数×100%
        String quarterFormat = StrUtil.deciFormat((incaseUpNum - incaseLastUpNum), incaseLastUpNum);
        //同比上报
        //计算同期季度的开始日期
        Date previousYearStart = cn.hutool.core.date.DateUtil.beginOfMonth(cn.hutool.core.date.DateUtil.offsetMonth(date, -12));
        Date previousYearEnd = cn.hutool.core.date.DateUtil.endOfMonth(cn.hutool.core.date.DateUtil.offsetMonth(date, -10));
        String previousYearStartStr = DateUtil.format(previousYearStart, "yyyy-MM-dd") + " 00:00:00";
        String previousYearEndStr = DateUtil.format(previousYearEnd, "yyyy-MM-dd") + " 23:59:59";
        params.put("startDate", previousYearStartStr);
        params.put("endDate", previousYearEndStr);
        params.put("searchType", "dish");
        int incaseLastYearUpNum = sdsQcincaseMapper.getMrlistOfDeptCount(params);
        //同比: 同比增长率＝（本期数－同期数）÷同期数×100%
        String yearFormat = StrUtil.deciFormat((incaseUpNum - incaseLastYearUpNum), incaseLastYearUpNum);

        int currentYear = cn.hutool.core.date.DateUtil.year(date);
        // 计算本季度的月份范围
        int currentQuarter = cn.hutool.core.date.DateUtil.quarter(date);
        switch (currentQuarter) {
            case 1:
                params.put("startMonth", 1);
                params.put("endMonth", 3);
                break;
            case 2:
                params.put("startMonth", 4);
                params.put("endMonth", 6);
                break;
            case 3:
                params.put("startMonth", 7);
                params.put("endMonth", 9);
                break;
            default:
                params.put("startMonth", 10);
                params.put("endMonth", 12);
        }
        params.put("year", currentYear);
        List<SdsDimDataEntity> monthDimData = sdsDimDataService.getUpMonth(params);
        //月均上报例数
        List<Map<String, Object>> list2 = new ArrayList<>();
        if (CommonUtil.isNotEmpty(monthDimData)) {
            for (SdsDimDataEntity sdsDimDataEntity : monthDimData) {
                Map<String, Object> map1 = new HashMap<>();
                String key = currentYear + String.format("%02d", sdsDimDataEntity.getDimMonth());
                map1.put("upYear", key);
                map1.put("upNum", sdsDimDataEntity.getMrCount());
                list2.add(map1);
            }
            list2 = list2.stream().sorted(Comparator.comparing(o -> o.get("upYear").toString())).collect(Collectors.toList());
        }

        params.put("startDate", startDate);
        params.put("endDate", endDate);
        params.put("qcTimeDimens", "year");
        List<AnalysisSdsPortalVo> upEntityList = sdsQcincaseDataService.selectQCUpLoadData(params);
        String upMaxEntityName = "";
        //上报病例最多的病种例数
        int upMaxEntityNameNum = 0;
        //上报病例最少的病种
        String upMinEntityName = "";
        //上报病例最少的病种例数
        int upMinEntityNameNum = 0;
        if (CommonUtil.isNotEmpty(upEntityList)) {
            //上报病例最多的病种
            List<AnalysisSdsPortalVo> sortedUpEntity = upEntityList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getCount)).collect(Collectors.toList());
            AnalysisSdsPortalVo maxUpEntity = sortedUpEntity.get(sortedUpEntity.size() - 1);
            upMaxEntityName = maxUpEntity.getDescription();
            //上报病例最多的病种例数
            upMaxEntityNameNum = maxUpEntity.getCount();
            //上报病例最少的病种
            AnalysisSdsPortalVo minUpEntity = sortedUpEntity.get(0);
            upMinEntityName = minUpEntity.getDescription();
            //上报病例最少的病种例数
            upMinEntityNameNum = minUpEntity.getCount();
        }

        //上报科室
        List<AnalysisSdsPortalVo> upLocList = sdsQcincaseDataService.selectLocUpLoadData(params);
        int upLocNum = upLocList.size();
        String upLocName = "";
        //上报病例最多科室
        String upMaxLocName = "";
        //上报病例最多科室例数
        int upMaxLocNum = 0;
        //上报病例数最少的科室
        String upMinLocName = "";
        //上报病例最少科室例数
        int upMinLocNum = 0;
        if (CommonUtil.isNotEmpty(upLocList)) {
            //前五的科室
            List<AnalysisSdsPortalVo> sortedUpLocList = upLocList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getCount).reversed()).collect(Collectors.toList());
            int i = 0;
            for (AnalysisSdsPortalVo analysisSdsPortalVo : sortedUpLocList) {
                i++;
                if (i > 5) break;
                upLocName += analysisSdsPortalVo.getDescription() + "、";
            }
            //上报病例最多科室
            upMaxLocName = sortedUpLocList.get(0).getDescription();
            //上报病例最多科室例数
            upMaxLocNum = sortedUpLocList.get(0).getCount();
            //上报病例数最少的科室
            upMinLocName = sortedUpLocList.get(sortedUpLocList.size() - 1).getDescription();
            //上报病例最少科室例数
            upMinLocNum = sortedUpLocList.get(sortedUpLocList.size() - 1).getCount();
        }

        // 10日内填报率前五的科室名称
        String in10DaysReportedLocNameTop5 = "";
        // 10日内填报率前五的科室数据
        String in10DaysReportedLocDataTop5 = "";
        // 超过10日未上报率前五的科室名称
        String over10DaysNotReportedLocNameTop5 = "";
        // 超过10日未上报率前五的科室数据
        String over10DaysNotReportedLocDataTop5 = "";
        // 未上报人数前五的科室名称
        String notReportedLocNameTop5 = "";
        // 未上报人数前五的科室数据
        String notReportedLocDataTop5 = "";

        // 科室统计：10日内填报率、超过10日未上报率、未上报人数
        List<Map<String, Object>> locIndexList = sdsQcincaseDataMapper.selectLocLoadData(params);
        if (CommonUtil.isNotEmpty(locIndexList)) {
            // 10日内填报率前五的科室
            List<Map<String, Object>> sortedLocIndexList = locIndexList.stream().sorted(Comparator.comparing(o -> new BigDecimal(o.get("in10DaysReportedRate").toString()))).collect(Collectors.toList());
            for (int i = 1; i <= sortedLocIndexList.size(); i++) {
                if (i > 5) {
                    break;
                }
                in10DaysReportedLocNameTop5 += sortedLocIndexList.get(sortedLocIndexList.size() - i).get("locName").toString() + "、";
                in10DaysReportedLocDataTop5 += sortedLocIndexList.get(sortedLocIndexList.size() - i).get("in10DaysReportedRate").toString() + "%、";
            }
            // 10日内未上报率前五的科室
            List<Map<String, Object>> sortedLocIndexList1 = locIndexList.stream().sorted(Comparator.comparing(o -> new BigDecimal(o.get("over10DaysNotReportedRate").toString()))).collect(Collectors.toList());
            for (int i = 1; i <= sortedLocIndexList1.size(); i++) {
                if (i > 5) {
                    break;
                }
                over10DaysNotReportedLocNameTop5 += sortedLocIndexList1.get(sortedLocIndexList1.size() - i).get("locName").toString() + "、";
                over10DaysNotReportedLocDataTop5 += sortedLocIndexList1.get(sortedLocIndexList1.size() - i).get("over10DaysNotReportedRate").toString() + "%、";
            }
            // 未上报人数前五的科室
            List<Map<String, Object>> sortedLocIndexList2 = locIndexList.stream().sorted(Comparator.comparing(o -> new BigDecimal(o.get("notReportedCount").toString()))).collect(Collectors.toList());
            for (int i = 1; i <= sortedLocIndexList2.size(); i++) {
                if (i > 5) {
                    break;
                }
                notReportedLocNameTop5 += sortedLocIndexList2.get(sortedLocIndexList2.size() - i).get("locName").toString() + "、";
                notReportedLocDataTop5 += sortedLocIndexList2.get(sortedLocIndexList2.size() - i).get("notReportedCount").toString() + "、";
            }
        }

        params.put("startDate", startDate);
        params.put("endDate", endDate);
        List<AnalysisSdsMstaDto> statisList = analysisSdsMstaMapper.selectMstaDataByEntity(params);
        //statisList不为空
        if (CommonUtil.isNotEmpty(statisList)) {
            statisList.remove(statisList.size() - 1);//查询结果有合计行，需要删除合计行
            for (AnalysisSdsMstaDto analysisSdsMstaDto : statisList) {
                Long entityId = analysisSdsMstaDto.getEntityId();
                if (CommonUtil.isEmpty(entityId)) {
                    continue;
                }
                SdsQcentityEntity sdsQcentityEntity = sdsQcentityService.selectById(entityId);
                analysisSdsMstaDto.setEntityDesc(sdsQcentityEntity.getBtDesc());
                Integer hosDays = analysisSdsMstaDto.getHosDays();
                Float hosCost = analysisSdsMstaDto.getHosCost();
                Float consumCost1 = analysisSdsMstaDto.getConsumCost1();
                Float consumCost2 = analysisSdsMstaDto.getConsumCost2();
                Float consumCost3 = analysisSdsMstaDto.getConsumCost3();
                Float consumCost4 = analysisSdsMstaDto.getConsumCost4();
                Float consumCost = consumCost1 + consumCost2 + consumCost3;
                analysisSdsMstaDto.setConsumCost(consumCost);
                Float medeCost = analysisSdsMstaDto.getMedeCost();
                Integer consistentNum = analysisSdsMstaDto.getConsistentNum();
                BigDecimal decimalconsistentNum = new BigDecimal(consistentNum);
                if (!Objects.equals(0, consistentNum)) {
                    DecimalFormat df = new DecimalFormat("0.00");
                    String averageHosDays = df.format((float) hosDays / consistentNum);
                    String averageHosCost = df.format(hosCost / consistentNum);
                    String averageMedeCost = df.format(medeCost / consistentNum);
                    String averageConsumCost = df.format(consumCost / consistentNum);
                    BigDecimal decimalDeathNum = new BigDecimal(analysisSdsMstaDto.getDeathNum());
                    Double r = decimalDeathNum.divide(decimalconsistentNum, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).doubleValue();
                    analysisSdsMstaDto.setAverageHosDays(averageHosDays);
                    analysisSdsMstaDto.setAverageHosCost(averageHosCost);
                    analysisSdsMstaDto.setAverageMedeCost(averageMedeCost);
                    analysisSdsMstaDto.setAverageConsumCost(averageConsumCost);
                    analysisSdsMstaDto.setAverageDeathNumRate(Double.toString(r));
                }
            }
        }

        String avgMaxFeeEntityName = "";
        //次均住院费用最高
        String avgMaxFee = "";
        //次均住院费用最低病种
        String avgMinFeeEntityName = "";
        //次均住院费用最低
        String avgMinFee = "";
        String avgMaxDayEntityName = "";
        //次均住院日最高
        String avgMaxDay = "";
        //次均住院日最低病种
        String avgMinDayEntityName = "";
        //次均住院日最低
        String avgMinDay = "";
        String deadFirstEntityName = "";
        //病死率最高病死率
        String deadFirstFormat = "";
        //病死率第二高
        String deadSecEntityName = "";
        //病死率第二高病死率
        String deadSecFormat = "";
        //病死率第三高
        String deadThirdEntityName = "";
        //病死率第三高病死率
        String deadThirdFormat = "";
        String avgMaxMedeCostEntityName = "";
        String avgMaxMedeCost = "";
        String avgMinMedeCostEntityName = "";
        String avgMinMedeCost = "";
        String avgMaxConsumCostEntityName = "";
        String avgMaxConsumCost = "";
        String avgMinConsumCostEntityName = "";
        String avgMinConsumCost = "";
        if (CommonUtil.isNotEmpty(statisList)) {
            //次均住院费用最高病种
            List<AnalysisSdsMstaDto> sortedHospFee = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageHosCost, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            )).collect(Collectors.toList());
            for (int i = 0; i < sortedHospFee.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxFeeEntityName += sortedHospFee.get(sortedHospFee.size() - (i + 1)).getEntityDesc() + "、";
                //次均住院费用最高
                avgMaxFee += sortedHospFee.get(sortedHospFee.size() - (i + 1)).getAverageHosCost() + "、";
                //次均住院费用最低病种
                avgMinFeeEntityName += sortedHospFee.get(i).getEntityDesc() + "、";
                //次均住院费用最低
                avgMinFee += sortedHospFee.get(i).getAverageHosCost() + "、";
            }


            //次均住院日最高病种
            List<AnalysisSdsMstaDto> sortedHospDay = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageHosDays, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            )).collect(Collectors.toList());
            for (int i = 0; i < sortedHospDay.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxDayEntityName += sortedHospDay.get(sortedHospDay.size() - (i + 1)).getEntityDesc() + "、";
                //次均住院日最高
                avgMaxDay += sortedHospDay.get(sortedHospDay.size() - (i + 1)).getAverageHosDays() + "、";
                //次均住院日最低病种
                avgMinDayEntityName += sortedHospDay.get(i).getEntityDesc() + "、";
                //次均住院日最低
                avgMinDay += sortedHospDay.get(i).getAverageHosDays() + "、";
            }

            //病死率最高
            List<AnalysisSdsMstaDto> sortedAverageDeathNumRate = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageDeathNumRate, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            ).reversed()).collect(Collectors.toList());

            deadFirstEntityName = sortedAverageDeathNumRate.get(0).getEntityDesc();
            //病死率最高病死率
            deadFirstFormat = sortedAverageDeathNumRate.get(0).getAverageDeathNumRate();
            //病死率第二高
            deadSecEntityName = sortedAverageDeathNumRate.get(1).getEntityDesc();
            //病死率第二高病死率
            deadSecFormat = sortedAverageDeathNumRate.get(1).getAverageDeathNumRate();
            //病死率第三高
            deadThirdEntityName = sortedAverageDeathNumRate.get(2).getEntityDesc();
            //病死率第三高病死率
            deadThirdFormat = sortedAverageDeathNumRate.get(2).getAverageDeathNumRate();
            //平均药费
            List<AnalysisSdsMstaDto> sortedMedeCost = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageMedeCost, (x, y) -> {
                BigDecimal bigDecimalA = new BigDecimal(x);
                BigDecimal bigDecimalB = new BigDecimal(y);
                return bigDecimalA.compareTo(bigDecimalB);
            })).collect(Collectors.toList());
            for (int i = 0; i < sortedMedeCost.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxMedeCostEntityName += sortedMedeCost.get(sortedMedeCost.size() - (i + 1)).getEntityDesc() + "、";
                avgMaxMedeCost += sortedMedeCost.get(sortedMedeCost.size() - (i + 1)).getAverageMedeCost() + "、";
                avgMinMedeCostEntityName += sortedMedeCost.get(i).getEntityDesc() + "、";
                avgMinMedeCost += sortedMedeCost.get(i).getAverageMedeCost() + "、";
            }

            //平均耗材费
            List<AnalysisSdsMstaDto> sortedAverageConsumCost = statisList.stream().sorted(Comparator.comparing(AnalysisSdsMstaDto::getAverageConsumCost, (x, y) -> {
                BigDecimal bigDecimalA = new BigDecimal(x);
                BigDecimal bigDecimalB = new BigDecimal(y);
                return bigDecimalA.compareTo(bigDecimalB);
            })).collect(Collectors.toList());
            for (int i = 0; i < sortedAverageConsumCost.size(); i++) {
                if (i >= 5) {
                    break;
                }
                avgMaxConsumCostEntityName += sortedAverageConsumCost.get(sortedAverageConsumCost.size() - (i + 1)).getEntityDesc() + "、";
                avgMaxConsumCost += sortedAverageConsumCost.get(sortedAverageConsumCost.size() - (i + 1)).getAverageConsumCost() + "、";
                avgMinConsumCostEntityName += sortedAverageConsumCost.get(i).getEntityDesc() + "、";
                avgMinConsumCost += sortedAverageConsumCost.get(i).getAverageConsumCost() + "、";
            }
        }

        // 费用和住院日增幅、降幅数据处理
        // 费用map
        Map<String, BigDecimal[]> diseaseCosts = new HashMap<>();
        // 住院日map
        Map<String, BigDecimal[]> diseaseUseTime = new HashMap<>();
        // 当前选择年的数据
        for (AnalysisSdsMstaDto cost : statisList) {
            BigDecimal consistentNum = BigDecimal.valueOf(cost.getConsistentNum());
            Long entityId = cost.getEntityId();
            String entityName = QcEntityCache.me().getQcEntityById(entityId).getBtDesc();
            diseaseCosts.putIfAbsent(entityName, new BigDecimal[2]);
            diseaseCosts.get(entityName)[0] = BigDecimal.valueOf(cost.getHosCost()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
            diseaseUseTime.putIfAbsent(entityName, new BigDecimal[2]);
            diseaseUseTime.get(entityName)[0] = BigDecimal.valueOf(cost.getHosDays()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
        }
        // 前一年的统计数据
        Map<String, Object> lastParams = new HashMap<>();
        lastParams.putAll(params);
        lastParams.put("startDate", previousQuarterStartStr);
        lastParams.put("endDate", previousQuarterEndStr);
        List<AnalysisSdsMstaDto> lastYearStatisList = analysisSdsMstaMapper.selectMstaDataByEntity(lastParams);
        for (AnalysisSdsMstaDto cost : lastYearStatisList) {
            BigDecimal consistentNum = BigDecimal.valueOf(cost.getConsistentNum());
            Long entityId = cost.getEntityId();
            String entityName = QcEntityCache.me().getQcEntityById(entityId).getBtDesc();
            if (diseaseCosts.get(entityName)!=null) {
                diseaseCosts.get(entityName)[1] = BigDecimal.valueOf(cost.getHosCost()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
            }
            if (diseaseUseTime.get(entityName)!=null) {
                diseaseUseTime.get(entityName)[1] = BigDecimal.valueOf(cost.getHosDays()).divide(consistentNum, 2, BigDecimal.ROUND_HALF_UP);
            }
        }

        // 费用增幅、降幅
        List<Map<String, Object>> costRatioList = new ArrayList<>();
        for (Map.Entry<String, BigDecimal[]> entry : diseaseCosts.entrySet()) {
            Map<String, Object> costRatioMap = new HashMap<>();
            // 处理某一年没有某个病种的情况，将缺失的费用默认为没有变化
            if (entry.getValue()[0] == null) {
                entry.getValue()[0] = BigDecimal.valueOf(0);
            } else if (entry.getValue()[1] == null) {
                entry.getValue()[1] = BigDecimal.valueOf(0);
            }

            costRatioMap.put("entityName", entry.getKey());
            costRatioMap.put("lastQuarterData", entry.getValue()[1]);
            costRatioMap.put("thisQuarterData", entry.getValue()[0]);
            // 使用BigDecimal计算成本比率，以保留精度并避免科学计数法
            if (entry.getValue()[1].compareTo(BigDecimal.valueOf(0)) == 0) {
                costRatioMap.put("costRatio", BigDecimal.valueOf(0));
            } else {
                BigDecimal costRatioValue = entry.getValue()[0]
                        .subtract(entry.getValue()[1])
                        .divide(entry.getValue()[1], 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                costRatioMap.put("costRatio", costRatioValue);
            }

            costRatioList.add(costRatioMap);
        }
        // 费用按照降幅排序
        costRatioList.sort(Comparator.comparing(map -> (BigDecimal) map.get("costRatio")));

        // 住院日增幅、降幅
        List<Map<String, Object>> useTimeRatioList = new ArrayList<>();
        for (Map.Entry<String, BigDecimal[]> entry : diseaseUseTime.entrySet()) {
            Map<String, Object> useTimeRatioMap = new HashMap<>();
            // 处理某一年没有某个病种的情况，将缺失的住院日默认为没有变化
            BigDecimal[] values = entry.getValue();
            if (values[0] == null) {
                values[0] = BigDecimal.valueOf(0);
            }
            if (values[1] == null) {
                values[1] = BigDecimal.valueOf(0);
            }

            useTimeRatioMap.put("entityName", entry.getKey());
            useTimeRatioMap.put("lastQuarterData", entry.getValue()[1]);
            useTimeRatioMap.put("thisQuarterData", entry.getValue()[0]);
            // 使用BigDecimal计算成本比率，以保留精度并避免科学计数法
            if (entry.getValue()[1].compareTo(BigDecimal.valueOf(0)) == 0) {
                useTimeRatioMap.put("useTimeRatio", BigDecimal.valueOf(0));
            } else {
                BigDecimal useTimeRatioValue = entry.getValue()[0]
                        .subtract(entry.getValue()[1])
                        .divide(entry.getValue()[1], 4, RoundingMode.HALF_UP)
                        .multiply(BigDecimal.valueOf(100));
                useTimeRatioMap.put("useTimeRatio", useTimeRatioValue);
            }

            useTimeRatioList.add(useTimeRatioMap);
        }
        // 住院日按照降幅排序
        useTimeRatioList.sort(Comparator.comparing(map -> (BigDecimal) map.get("useTimeRatio")));

        // 费用降幅最大5个病种
        String costRatioMaxEntityName = "";
        // 费用降幅最大5个病种降幅
        String costRatioMax = "";
        // 费用增幅最大5个病种
        String costRatioMinEntityName = "";
        // 费用增幅最大5个病种增幅
        String costRatioMin = "";
        for (int i = 0; i < costRatioList.size(); i++) {
            if (i >= 5) {
                break;
            }
            costRatioMaxEntityName += costRatioList.get(i).get("entityName") + "、";
            costRatioMax += costRatioList.get(i).get("costRatio") + "、";
            costRatioMinEntityName += costRatioList.get(costRatioList.size() - (i + 1)).get("entityName") + "、";
            costRatioMin += costRatioList.get(costRatioList.size() - (i + 1)).get("costRatio") + "、";
        }

        // 住院日降幅最大5个病种
        String useTimeRatioMaxEntityName = "";
        // 住院日降幅最大5个病种降幅
        String useTimeRatioMax = "";
        // 住院日增幅最大5个病种
        String useTimeRatioMinEntityName = "";
        // 住院日增幅最大5个病种增幅
        String useTimeRatioMin = "";
        for (int i = 0; i < useTimeRatioList.size(); i++) {
            if (i >= 5) {
                break;
            }
            useTimeRatioMaxEntityName += useTimeRatioList.get(i).get("entityName") + "、";
            useTimeRatioMax += useTimeRatioList.get(i).get("useTimeRatio") + "、";
            useTimeRatioMinEntityName += useTimeRatioList.get(useTimeRatioList.size() - (i + 1)).get("entityName") + "、";
            useTimeRatioMin += useTimeRatioList.get(useTimeRatioList.size() - (i + 1)).get("useTimeRatio") + "、";
        }

        List<AnalysisSdsPortalVo> ratioList = new ArrayList<>();
        for (Long entityId : entityIds) {
            //统计病种最新一条数据
            AnalysisSdsPortalVo analysisSdsPortalVo = sdsQcincaseDataService.selectARatioByTime(entityId, params);
            if (!StringUtils.isEmpty(analysisSdsPortalVo)) {
                String s = analysisSdsPortalVo.getaRatio();
                String[] split = s.split(";");
                //过滤采集率为零的病种
                if (Objects.equals("0", split[0])) {
                    continue;
                }
                String r = split[2];
                analysisSdsPortalVo.setaRatio(r.substring(0, r.length() - 1));
                ratioList.add(analysisSdsPortalVo);
            }
        }

        //自动采集率中位数
        String avgAutoAcq = "";
        //采集率最高的病种
        String autoAcqMaxEntityName = "";
        //采集率最高
        String autoAcqMax = "";
        //采集率最低的病种
        String autoAcqMinEntityName = "";
        //采集率最高
        String autoAcqMin = "";
        if (CommonUtil.isNotEmpty(ratioList)) {
            List<AnalysisSdsPortalVo> sortedARatio = ratioList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getaRatio, (x, y) -> {
                        BigDecimal dataA = new BigDecimal(x);
                        BigDecimal dataB = new BigDecimal(y);
                        return dataA.compareTo(dataB);
                    }
            )).collect(Collectors.toList());
            //自动采集率中位数
            avgAutoAcq = median(sortedARatio);
            for (int i = 0; i < sortedARatio.size(); i++) {
                if (i >= 10) {
                    break;
                }
                //采集率最高的病种
                autoAcqMaxEntityName += sortedARatio.get(sortedARatio.size() - (i + 1)).getCode() + "、";
                //采集率最高
                autoAcqMax += sortedARatio.get(sortedARatio.size() - (i + 1)).getaRatio() + "、";
                if (i < 5) {
                    //采集率最低的病种
                    autoAcqMinEntityName += sortedARatio.get(i).getCode() + "、";
                    //采集率最高
                    autoAcqMin += sortedARatio.get(i).getaRatio() + "、";
                }
            }

        }


        List<AnalysisSdsPortalVo> useTimeList = new ArrayList<>();
        a:
        for (Long entityId : entityIds) {
            List<AnalysisSdsPortalVo> sdsPortalVoList = sdsQcincaseDataService.selectUseTimeByTime(entityId, params);
            if (sdsPortalVoList.isEmpty()) {
                continue a;
            }
            Long sumMin = 0l;
            String s = sdsPortalVoList.get(0).getDescription();
            String c = sdsPortalVoList.get(0).getCode();
            List<Long> useTime = new ArrayList<>();
            b:
            for (AnalysisSdsPortalVo analysisSdsPortalVo : sdsPortalVoList) {
                sumMin += analysisSdsPortalVo.getFillUseTime();
                useTime.add(analysisSdsPortalVo.getFillUseTime());
            }
            AnalysisSdsPortalVo analysisSdsPortalVo = new AnalysisSdsPortalVo();
            String avgUseTime = StrUtil.deciFormatLong(sumMin, sdsPortalVoList.size());
            analysisSdsPortalVo.setDescription(s);
            analysisSdsPortalVo.setCode(c);
            analysisSdsPortalVo.setAvgUseTime(avgUseTime);
            analysisSdsPortalVo.setUseTime(useTime);
            useTimeList.add(analysisSdsPortalVo);

        }

        String avgFillingMaxEntityName = "";
        //填报平均用时最长
        String avgFillingMax = "";
        //填报平均用时最短的病种
        String avgFillingMinEntityName = "";
        //填报平均用时最短
        String avgFillingMin = "";
        if (CommonUtil.isNotEmpty(useTimeList)) {
            List<AnalysisSdsPortalVo> sortedUseTime = useTimeList.stream().sorted(Comparator.comparing(AnalysisSdsPortalVo::getAvgUseTime, (x, y) -> {
                        BigDecimal bigDecimalA = new BigDecimal(x);
                        BigDecimal bigDecimalB = new BigDecimal(y);
                        return bigDecimalA.compareTo(bigDecimalB);
                    }
            )).collect(Collectors.toList());
            for (int i = 0; i < sortedUseTime.size(); i++) {
                if (i >= 10) {
                    break;
                }
                //填报平均用时最长的病种
                avgFillingMaxEntityName += sortedUseTime.get(sortedUseTime.size() - (i + 1)).getCode() + "、";
                //填报平均用时最长
                avgFillingMax += sortedUseTime.get(sortedUseTime.size() - (i + 1)).getAvgUseTime() + "、";
                if (i < 5) {
                    //填报平均用时最短的病种
                    avgFillingMinEntityName += sortedUseTime.get(i).getCode() + "、";
                    //填报平均用时最短
                    avgFillingMin += sortedUseTime.get(i).getAvgUseTime() + "、";
                }
            }
        }

        // 10大国考病种和三大重点科室14个病种报表统计（病例数、平均住院日、次均费用、病死率、并发症）
        // 10大国考病种
        List<AnalysisSdsMstaDto> nationalExamDiseaseList = this.calculateAndStoreStatistics(params, "NationalExamDisease");
        // 三大重点科室14个病种报表统计
        List<AnalysisSdsMstaDto> keyDeptDiseaseList = this.calculateAndStoreStatistics(params, "KeyDeptDisease");


        // 院内重点病种指标
        //一级指标（单病种名称）
        List<Map<String, Object>> keyStatisticsList = calculateAndStoreKeyStatistics(params);


        //ftl赋值
        dataMap.put("hospitalName", hospitalName);
        dataMap.put("reportDate", reportDate);
        dataMap.put("createDate", createDate);
        dataMap.put("dischPatientTotal", dischPatientTotal);
        dataMap.put("incaseNum", incaseNum);
        dataMap.put("incaseUpNum", incaseUpNum);
        dataMap.put("upFormat", upFormat);
        dataMap.put("incaseSysNum", incaseSysNum);
        dataMap.put("incaseActiveNum", incaseActiveNum);
        dataMap.put("sysFormat", sysFormat);
        dataMap.put("entityNum", entityNum);
        dataMap.put("notEntityNum", notEntityNum);
        dataMap.put("entityFormat", entityFormat);
        dataMap.put("incaseLastUpNum", incaseLastUpNum);
        dataMap.put("quarterFormat", quarterFormat);
        dataMap.put("yearFormat", yearFormat);
        dataMap.put("upMaxEntityName", upMaxEntityName);
        dataMap.put("upMaxEntityNameNum", upMaxEntityNameNum);
        dataMap.put("upMinEntityName", upMinEntityName);
        dataMap.put("upMinEntityNameNum", upMinEntityNameNum);
        dataMap.put("upLocNum", upLocNum);
        dataMap.put("upLocName", upLocName);
        dataMap.put("upMaxLocName", upMaxLocName);
        dataMap.put("upMaxLocNum", upMaxLocNum);
        dataMap.put("upMinLocName", upMinLocName);
        dataMap.put("upMinLocNum", upMinLocNum);
        dataMap.put("in10DaysReportedLocNameTop5", StringUtils.trimTrailingCharacter(in10DaysReportedLocNameTop5, '、'));
        dataMap.put("in10DaysReportedLocDataTop5", StringUtils.trimTrailingCharacter(in10DaysReportedLocDataTop5, '、'));
        dataMap.put("over10DaysNotReportedLocNameTop5", StringUtils.trimTrailingCharacter(over10DaysNotReportedLocNameTop5, '、'));
        dataMap.put("over10DaysNotReportedLocDataTop5", StringUtils.trimTrailingCharacter(over10DaysNotReportedLocDataTop5, '、'));
        dataMap.put("notReportedLocNameTop5", StringUtils.trimTrailingCharacter(notReportedLocNameTop5, '、'));
        dataMap.put("notReportedLocDataTop5", StringUtils.trimTrailingCharacter(notReportedLocDataTop5, '、'));
        dataMap.put("avgMaxFeeEntityName", StringUtils.trimTrailingCharacter(avgMaxFeeEntityName, '、'));
        dataMap.put("avgMaxFee", StringUtils.trimTrailingCharacter(avgMaxFee, '、'));
        dataMap.put("avgMinFeeEntityName", StringUtils.trimTrailingCharacter(avgMinFeeEntityName, '、'));
        dataMap.put("avgMinFee", StringUtils.trimTrailingCharacter(avgMinFee, '、'));
        dataMap.put("costRatioMaxEntityName", StringUtils.trimTrailingCharacter(costRatioMaxEntityName, '、'));
        dataMap.put("costRatioMax", StringUtils.trimTrailingCharacter(costRatioMax, '、'));
        dataMap.put("costRatioMinEntityName", StringUtils.trimTrailingCharacter(costRatioMinEntityName, '、'));
        dataMap.put("costRatioMin", StringUtils.trimTrailingCharacter(costRatioMin, '、'));
        dataMap.put("costRatioList", costRatioList);
        dataMap.put("avgMaxDayEntityName", StringUtils.trimTrailingCharacter(avgMaxDayEntityName, '、'));
        dataMap.put("avgMaxDay", StringUtils.trimTrailingCharacter(avgMaxDay, '、'));
        dataMap.put("avgMinDayEntityName", StringUtils.trimTrailingCharacter(avgMinDayEntityName, '、'));
        dataMap.put("avgMinDay", StringUtils.trimTrailingCharacter(avgMinDay, '、'));
        dataMap.put("useTimeRatioMinEntityName", StringUtils.trimTrailingCharacter(useTimeRatioMinEntityName, '、'));
        dataMap.put("useTimeRatioMin", StringUtils.trimTrailingCharacter(useTimeRatioMin, '、'));
        dataMap.put("useTimeRatioMaxEntityName", StringUtils.trimTrailingCharacter(useTimeRatioMaxEntityName, '、'));
        dataMap.put("useTimeRatioMax", StringUtils.trimTrailingCharacter(useTimeRatioMax, '、'));
        dataMap.put("useTimeRatioList", useTimeRatioList);
        dataMap.put("deadFirstEntityName", deadFirstEntityName);
        dataMap.put("deadFirstFormat", deadFirstFormat);
        dataMap.put("deadSecEntityName", deadSecEntityName);
        dataMap.put("deadSecFormat", deadSecFormat);
        dataMap.put("deadThirdEntityName", deadThirdEntityName);
        dataMap.put("deadThirdFormat", deadThirdFormat);
        dataMap.put("avgAutoAcq", avgAutoAcq);
        dataMap.put("autoAcqMaxEntityName", StringUtils.trimTrailingCharacter(autoAcqMaxEntityName, '、'));
        dataMap.put("autoAcqMax", StringUtils.trimTrailingCharacter(autoAcqMax, '、'));
        dataMap.put("autoAcqMinEntityName", StringUtils.trimTrailingCharacter(autoAcqMinEntityName, '、'));
        dataMap.put("autoAcqMin", StringUtils.trimTrailingCharacter(autoAcqMin, '、'));
        dataMap.put("avgFillingMaxEntityName", StringUtils.trimTrailingCharacter(avgFillingMaxEntityName, '、'));
        dataMap.put("avgFillingMax", StringUtils.trimTrailingCharacter(avgFillingMax, '、'));
        dataMap.put("avgFillingMinEntityName", StringUtils.trimTrailingCharacter(avgFillingMinEntityName, '、'));
        dataMap.put("avgFillingMin", StringUtils.trimTrailingCharacter(avgFillingMin, '、'));
        dataMap.put("avgMaxMedeCostEntityName", StringUtils.trimTrailingCharacter(avgMaxMedeCostEntityName, '、'));
        dataMap.put("avgMaxMedeCost", StringUtils.trimTrailingCharacter(avgMaxMedeCost, '、'));
        dataMap.put("avgMinMedeCostEntityName", StringUtils.trimTrailingCharacter(avgMinMedeCostEntityName, '、'));
        dataMap.put("avgMinMedeCost", StringUtils.trimTrailingCharacter(avgMinMedeCost, '、'));
        dataMap.put("avgMaxConsumCostEntityName", StringUtils.trimTrailingCharacter(avgMaxConsumCostEntityName, '、'));
        dataMap.put("avgMaxConsumCost", StringUtils.trimTrailingCharacter(avgMaxConsumCost, '、'));
        dataMap.put("avgMinConsumCostEntityName", StringUtils.trimTrailingCharacter(avgMinConsumCostEntityName, '、'));
        dataMap.put("avgMinConsumCost", StringUtils.trimTrailingCharacter(avgMinConsumCost, '、'));

        dataMap.put("recentQuarterMonthExcelData", list2);
        dataMap.put("nationalExamDiseaseList", nationalExamDiseaseList);
        dataMap.put("keyDeptDiseaseList", keyDeptDiseaseList);
        dataMap.put("keyStatisticsList", keyStatisticsList);
        return dataMap;
    }

    /**
     * 计算统计国考和重点科室病种数据
     *
     * @param params
     * @param configType
     * @return
     */
    public List<AnalysisSdsMstaDto> calculateAndStoreStatistics(Map<String, Object> params, String configType) {
        String DiseaseCodeStr = CdcConfigCache.me().getValueByKey("SDS", configType);
        if (CommonUtil.isEmpty(DiseaseCodeStr)) {
            return null;
        }
        // 获取病种ID
        String nationalExamDiseaseIdStr = "";
        for (String diseaseCode : DiseaseCodeStr.split(",")) {
            SdsQcentityEntity qcentity = new SdsQcentityEntity();
            qcentity.setAbbrev(diseaseCode);
            qcentity = sdsQcentityMapper.selectOne(qcentity);
            if (qcentity != null) {
                nationalExamDiseaseIdStr += qcentity.getId() + ",";
            }
        }
        params.put("qcEntity", nationalExamDiseaseIdStr);
        List<AnalysisSdsMstaDto> diseaseStaticsList = analysisSdsMstaMapper.selectMstaDataByEntity(params);
        Iterator<AnalysisSdsMstaDto> itr = diseaseStaticsList.iterator();
        while (itr.hasNext()) {
            AnalysisSdsMstaDto analysisSdsMstaDto = itr.next();
            Long entityId = analysisSdsMstaDto.getEntityId();
            SdsQcentityEntity sdsQcentityEntity = QcEntityCache.me().getQcEntityById(entityId);
            if (sdsQcentityEntity.getIsActive() == 3) {// 如果病种状态是灰色，不参与统计
                itr.remove();
                continue;
            }
            analysisSdsMstaDto.setEntityDesc(sdsQcentityEntity.getBtDesc());
            Integer hosDays = analysisSdsMstaDto.getHosDays();
            Float hosCost = analysisSdsMstaDto.getHosCost();
            Float consumCost1 = analysisSdsMstaDto.getConsumCost1();
            Float consumCost2 = analysisSdsMstaDto.getConsumCost2();
            Float consumCost3 = analysisSdsMstaDto.getConsumCost3();
            Float consumCost4 = analysisSdsMstaDto.getConsumCost4();
            Float consumCost = consumCost1 + consumCost2 + consumCost3;
            analysisSdsMstaDto.setConsumCost(consumCost);
            Float medeCost = analysisSdsMstaDto.getMedeCost();
            Integer consistentNum = analysisSdsMstaDto.getConsistentNum();
            if (!Objects.equals(0, consistentNum)) {
                DecimalFormat df = new DecimalFormat("0.00");
                String averageHosDays = df.format((float) hosDays / consistentNum);
                String averageHosCost = df.format(hosCost / consistentNum);
                String averageMedeCost = df.format(medeCost / consistentNum);
                String averageConsumCost = df.format(consumCost / consistentNum);
                analysisSdsMstaDto.setAverageHosDays(averageHosDays);
                analysisSdsMstaDto.setAverageHosCost(averageHosCost);
                analysisSdsMstaDto.setAverageMedeCost(averageMedeCost);
                analysisSdsMstaDto.setAverageConsumCost(averageConsumCost);
            }
        }
        return diseaseStaticsList;
    }

    /**
     * 计算院内重点病种统计数据
     *
     * @param params
     * @return
     */
    public List<Map<String, Object>> calculateAndStoreKeyStatistics(Map<String, Object> params) {
        List<Map<String, Object>> entityList = sdsIndexHeaderMapper.selectImportantEntityHeader();
        // 创建表达式引擎对象
        JexlEngine engine = new JexlEngine();
        for (Map<String, Object> stringObjectMap : entityList) {
            Map<String, Object> map = new HashMap<>();
            Long entityId = Long.valueOf(stringObjectMap.get("entityId").toString());
            SdsQcentityEntity sdsQcentityEntity = QcEntityCache.me().getQcEntityById(entityId);
            map.put("qcEntity", entityId);
            map.put("headerType", 2);
            map.put("btIsActive", 1);
            map.put("isImportant", 1);
            // 二级指标
            List<SdsIndexHeaderEntity> sonList = sdsIndexHeaderMapper.list(map);
            stringObjectMap.put("colspan", sonList.size());
            // 该病种各月份入组记录ids
            params.put("entityId", entityId);
            List<Map<String, Object>> secondList = new ArrayList<>();
            List<AnalysisSdsPortalVo> monthIdsList = sdsQcincaseMapper.getMonthIds(params);
            if (monthIdsList!=null&&stringObjectMap.get("monthMap")==null) {
                stringObjectMap.put("monthMap", monthIdsList);
            }
            for (SdsIndexHeaderEntity sdsIndexHeaderEntity : sonList) {
                Map<String, Object> secondMap = new HashMap<>();
                secondMap.put("entityName", sdsQcentityEntity.getBtDesc());
                secondMap.put("indexFieldDesc", sdsIndexHeaderEntity.getTitle());
                Map<String, Object> resMap = new TreeMap<>();
                for (AnalysisSdsPortalVo sdsPortalVo : monthIdsList) {
                    String month = sdsPortalVo.getDate();
                    int inCaseCount = sdsPortalVo.getCount();
                    if (inCaseCount == 0) {
                        // 该月份没有患者
                        resMap.put(month, "-");
                        continue;
                    }
                    Map<String, Object> cal = new HashMap<>();
                    Map<String, Object> calDen = new HashMap<>();
                    String monthIds = sdsPortalVo.getIds();
                    String[] inCaseIdArr = monthIds.split(",");
                    a:
                    for (String s : inCaseIdArr) {
                        Long inCaseId = Long.valueOf(s);
                        //指标字段未配置
                        if (StringUtils.isEmpty(cal.get(month))) {
                            cal.put(month, 0);
                            calDen.put(month, 0);
                        }
                        List<SdsIndexFieldEntity> sdsIndexFieldEntityList = sdsIndexFieldMapper.selectList(new EntityWrapper<SdsIndexFieldEntity>()
                                .eq("index_header_id", sdsIndexHeaderEntity.getId()));
                        // 创建表达式语句
                        String expressionStr = sdsIndexHeaderEntity.getExpress();
                        String expressionDenStr = sdsIndexHeaderEntity.getExpressDen();
                        // 创建Context对象，为表达式中的未知数赋值
                        JexlContext context = new MapContext();
                        JexlContext contextDen = new MapContext();
                        for (SdsIndexFieldEntity sdsIndexFieldEntity : sdsIndexFieldEntityList) {
                            if (sdsIndexFieldEntity.getItemType() != 1) {
                                continue;
                            }
                            // 根据前置条件，计算项目显隐属性
                            Integer editPower = this.calcTriggerExp(inCaseId, FormItemCache.me().getFormItemById(sdsIndexFieldEntity.getItemId()), new HashMap<>());
                            if (editPower == 0) {
                                continue a;
                            }
                            String valueByFormIdAndCaseId = sdsQcfitemExecresultService.getValueByFormIdAndCaseId(sdsIndexFieldEntity.getItemId(), inCaseId);
                            if (!StringUtils.isEmpty(valueByFormIdAndCaseId) && !StringUtils.isEmpty(sdsIndexHeaderEntity.getExpress())) {
                                //对日期进行特殊处理
                                if (sdsIndexHeaderEntity.getField().contains("Time")) {
                                    if (com.dhcc.sds.util.DateUtil.isValidDate(valueByFormIdAndCaseId)) {
                                        valueByFormIdAndCaseId += " 00:00:00";
                                    }
                                    Date date = null;
                                    if (com.dhcc.sds.util.DateUtil.isValidDateTime(valueByFormIdAndCaseId)) {
                                        date = com.dhcc.sds.util.DateUtil.parseTime(valueByFormIdAndCaseId);
                                    }
                                    context.set(sdsIndexFieldEntity.getItemCode(), date != null ? date : valueByFormIdAndCaseId);
                                } else {
                                    context.set(sdsIndexFieldEntity.getItemCode(), valueByFormIdAndCaseId);
                                }
                            } else {
                                continue a;
                            }
                        }

                        for (SdsIndexFieldEntity sdsIndexFieldEntity : sdsIndexFieldEntityList) {
                            if (sdsIndexFieldEntity.getItemType() != 2) {
                                continue;
                            }
                            // 根据前置条件，计算项目显隐属性
                            Integer editPower = this.calcTriggerExp(inCaseId, FormItemCache.me().getFormItemById(sdsIndexFieldEntity.getItemId()), new HashMap<>());
                            if (editPower == 0) {
                                continue a;
                            }

                            String valueByFormIdAndCaseId = sdsQcfitemExecresultService.getValueByFormIdAndCaseId(sdsIndexFieldEntity.getItemId(), inCaseId);
                            if (!StringUtils.isEmpty(valueByFormIdAndCaseId) && !StringUtils.isEmpty(sdsIndexHeaderEntity.getExpressDen())) {
                                //对日期进行特殊处理
                                if (sdsIndexHeaderEntity.getField().contains("Time")) {
                                    if (com.dhcc.sds.util.DateUtil.isValidDate(valueByFormIdAndCaseId)) {
                                        valueByFormIdAndCaseId += " 00:00:00";
                                    }
                                    Date date = null;
                                    if (com.dhcc.sds.util.DateUtil.isValidDateTime(valueByFormIdAndCaseId)) {
                                        date = com.dhcc.sds.util.DateUtil.parseTime(valueByFormIdAndCaseId);
                                    }
                                    contextDen.set(sdsIndexFieldEntity.getItemCode(), date != null ? date : valueByFormIdAndCaseId);
                                } else {
                                    contextDen.set(sdsIndexFieldEntity.getItemCode(), valueByFormIdAndCaseId);
                                }
                            } else {
                                //对表达式为空和项目值为空进行处理
                                if (sdsIndexHeaderEntity.getField().contains("Time")) {
                                    contextDen.set(sdsIndexFieldEntity.getItemCode(), new Date());
                                } else if (sdsIndexHeaderEntity.getField().contains("Fee")) {
                                    contextDen.set(sdsIndexFieldEntity.getItemCode(), 0);
                                } else {
                                    contextDen.set(sdsIndexFieldEntity.getItemCode(), "");
                                }
                            }
                        }

                        Object evaluate = null;
                        if (!StringUtils.isEmpty(expressionStr)) {
                            // 使用表达式引擎创建表达式对象
                            Expression expression = engine.createExpression(expressionStr);
                            // 使用表达式对象计算
                            evaluate = expression.evaluate(context);
                        }
                        Object o = cal.get(month);
                        //费用
                        if (sdsIndexHeaderEntity.getField().contains("Fee")) {
                            double x = 0;
                            if (!StringUtils.isEmpty(o)) {
                                x = Double.parseDouble(o.toString());
                            }
                            double y = Double.parseDouble(evaluate.toString());
                            cal.put(month, x + y);
                        } else if (sdsIndexHeaderEntity.getField().contains("Day")) {
                            //天数
                            int x = 0;
                            if (!StringUtils.isEmpty(o)) {
                                x = Integer.parseInt(o.toString());
                            }
                            int y = Integer.parseInt(evaluate.toString());
                            cal.put(month, x + y);
                        } else {
                            //占比
                            int x = 0;
                            if (!StringUtils.isEmpty(o)) {
                                x = Integer.parseInt(o.toString());
                            }
                            if (Objects.equals(true, evaluate)) {
                                cal.put(month, x + 1);
                            } else {
                                cal.put(month, x);
                            }
                        }

                        if (!StringUtils.isEmpty(expressionDenStr)) {
                            // 使用表达式引擎创建表达式对象
                            Expression expression = engine.createExpression(expressionDenStr);
                            // 使用表达式对象计算
                            Object evaluateDen = expression.evaluate(contextDen);
                            Object obj = calDen.get(month);
                            //费用
                            if (sdsIndexHeaderEntity.getField().contains("Fee")) {
                                double x = 0;
                                if (!StringUtils.isEmpty(obj)) {
                                    x = Double.parseDouble(obj.toString());
                                }
                                double y = Double.parseDouble(evaluateDen.toString());
                                calDen.put(sdsIndexHeaderEntity.getField(), x + y);
                            } else if (sdsIndexHeaderEntity.getField().contains("Day")) {
                                //天数
                                int x = 0;
                                if (!StringUtils.isEmpty(obj)) {
                                    x = Integer.parseInt(obj.toString());
                                }
                                int y = Integer.parseInt(evaluateDen.toString());
                                calDen.put(month, x + y);
                            } else {
                                //占比
                                int x = 0;
                                if (!StringUtils.isEmpty(obj)) {
                                    x = Integer.parseInt(obj.toString());
                                }
                                if (Objects.equals(true, evaluateDen)) {
                                    calDen.put(month, x + 1);
                                } else {
                                    calDen.put(month, x);
                                }
                            }
                        } else {
                            calDen.put(month, inCaseCount);
                        }

                    }
                    //处理数据
                    for (HashMap.Entry<String, Object> entry : cal.entrySet()) {
                        String key = entry.getKey();
                        Object o = cal.get(key);
                        Object objDen = calDen.get(key);
                        if (key.contains("Fee")) {
                            double x = 0;
                            double y = 0;
                            if (!StringUtils.isEmpty(o)) {
                                x = Double.parseDouble(o.toString());
                            }
                            if (!StringUtils.isEmpty(objDen)) {
                                y = Double.parseDouble(objDen.toString());
                            } else {
                                y = Double.valueOf(inCaseCount);
                            }

                            Object val = null;
                            if (y == 0) {
                                val = 0;
                            } else {
                                val = StrUtil.deciFormatDouble(x, (int) y);
                            }
                            resMap.put(month, val);
                        } else if (key.contains("Day")) {
                            int x = 0;
                            int y = 0;
                            if (!StringUtils.isEmpty(o)) {
                                x = Integer.parseInt(o.toString());
                            }
                            if (!StringUtils.isEmpty(objDen)) {
                                y = Integer.parseInt(objDen.toString());
                            } else {
                                y = inCaseCount;
                            }
                            Object val = null;
                            if (y == 0) {
                                val = 0;
                            } else {
                                val = StrUtil.deciFormatU(x, y);
                            }
                            resMap.put(month, val);
                        } else {
                            int x = Integer.parseInt(o.toString());
                            int y = 0;
                            if (!StringUtils.isEmpty(o)) {
                                x = Integer.parseInt(o.toString());
                            }
                            if (!StringUtils.isEmpty(objDen)) {
                                y = Integer.parseInt(objDen.toString());
                            } else {
                                y = inCaseCount;
                            }
                            Object val = StrUtil.deciFormat(x, y);
                            resMap.put(month, val);
                        }
                    }

                }
                secondMap.put("resMap", resMap);
                secondList.add(secondMap);
            }
            // 病种名称
            stringObjectMap.put("entityName", sdsQcentityEntity.getBtDesc());
            // 二级指标
            stringObjectMap.put("secondList", secondList);
        }
        return entityList;
    }

    public Integer calcTriggerExp(Long mrListId, SdsQcformItemEntity formItem, Map<String, Object> editMap) {
        // 项目全部默认显示
        Integer editPower = 1;
        //1、ScriptEngineManager是JDK6提出的相关方法，这方式的主要目的就是用来对脚本语言的处理。
        //2、ScriptEngineManager是在java的javax.script的包下，是Java原生提供的脚本语言处理方法。
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        if (CommonUtil.isEmpty(formItem.getTriggerExp())) {
            return editPower;
        } else {
            // 带表达式的项目默认不显示，只有表达式条件成立之后才显示
            editPower = 0;
            String triggerExp = formItem.getTriggerExp();
            Long entityId = formItem.getEntityId();
            // 查找规则公式中括号以内的字符
            Pattern p = Pattern.compile(p1);// 查找规则公式中括号以内的字符
            // 替换关联项目的值
            Matcher m = p.matcher(triggerExp);
            while (m.find()) {// 遍历找到的所有括号
                if (m.group().contains("\"")) { // 如果里面是常量，则继续下一个
                    continue;
                }
                // 取得关联项目代码
                String itemCode = m.group().substring(1, m.group().length() - 1);
                // 通过项目代码查询项目id并取值
                String linkVal = "";
                if (editMap.get(itemCode) != null && (Integer) editMap.get(itemCode) == 0) {
                    linkVal = "";
                } else {
                    SdsQcformItemEntity linkItem = FormItemCache.me().getFormItemByCode(entityId, itemCode);
                    SdsQcfitemExecresultEntity linkItemExec = sdsQcfitemExecresultService.selectOne(
                            new EntityWrapper<SdsQcfitemExecresultEntity>().eq("form_item_id", linkItem.getId())
                                    .eq("in_case_id", mrListId));
                    // 如果有项目值为空，则默认不符合
                    if (!CommonUtil.isEmpty(linkItemExec)) {
                        linkVal = linkItemExec.getItemResult();
                    }
                }
                // 如果表达式有引号，那么是字符串比较，给项目值加上双引号
//                if (triggerExp.contains("\"")) {
                linkVal = "(\"" + linkVal + "\")";
//                }
                // 将值替换表达式中项目代码
                triggerExp = triggerExp.replace(m.group(), linkVal);
            }
            if (!triggerExp.matches(p3)) {
                String[] expArr = triggerExp.split(":", 2);
                String subExpType_l = expArr[0];
                String subExp_l = expArr[1];

                long divisor = 1;
                if (subExpType_l.contains("CALC")) {
                    switch (subExpType_l) {
                        case "CALC-h":
                            // 1小时毫秒数
                            divisor = 60 * 60 * 1000;
                            break;
                        case "CALC-m":
                            // 一分钟毫秒数
                            divisor = 60 * 1000;
                            break;
                        case "CALC-day":
                            // 一天毫秒数
                            divisor = 24 * 60 * 60 * 1000;
                            break;
                        case "CALC-month":
                            // 一个月毫秒数
                            divisor = 30l * 24l * 60l * 60l * 1000l;
                            break;
                        case "CALC-year":
                            // 一年毫秒数
                            divisor = 12l * 30l * 24l * 60l * 60l * 1000l;
                            break;
                        default:
                            break;
                    }
                    // 查找规则公式中小括号以内的值
                    // 替换关联项目的值
                    m = p.matcher(subExp_l);
                    String execExp = subExp_l;
                    while (m.find()) {
                        if ("()".equals(m.group()) || "(\"\")".equals(m.group())) {
                            execExp = execExp.replace(m.group(), "0");
                            continue;
                        }
                        String val = m.group().substring(1, m.group().length() - 1).replace("\"", "");
                        Long times = com.dhcc.sds.util.DateUtil.getTime(val);
                        int minutes = Math.toIntExact(times / divisor);
                        execExp = execExp.replace(val, String.valueOf(minutes));
                    }
                    triggerExp = triggerExp.replace(subExp_l, execExp);
                }
                triggerExp = triggerExp.replace(subExpType_l, "");
            } else {
                // 查找规则公式中大括号以内的字符
                Pattern pat3 = Pattern.compile(p3);
                // 替换关联项目的值
                Matcher m3 = pat3.matcher(triggerExp);
                while (m3.find()) {
                    // 大括号中间的表达式
                    String subExpStr_l = m3.group().substring(1, m3.group().length() - 1);
                    String[] expArr = subExpStr_l.split(":", 2);
                    String subExpType_l = expArr[0];
                    String subExp_l = expArr[1];

                    long divisor = 1;
                    if (subExpType_l.contains("CALC")) {
                        switch (subExpType_l) {
                            case "CALC-h":
                                // 1小时毫秒数
                                divisor = 60 * 60 * 1000;
                                break;
                            case "CALC-m":
                                // 一分钟毫秒数
                                divisor = 60 * 1000;
                                break;
                            case "CALC-day":
                                // 一天毫秒数
                                divisor = 24 * 60 * 60 * 1000;
                                break;
                            case "CALC-month":
                                // 一个月毫秒数
                                divisor = 30l * 24l * 60l * 60l * 1000l;
                                break;
                            case "CALC-year":
                                // 一年毫秒数
                                divisor = 12l * 30l * 24l * 60l * 60l * 1000l;
                                break;
                            default:
                                break;
                        }
                        // 查找规则公式中小括号以内的值
                        // 替换关联项目的值
                        m = p.matcher(subExp_l);
                        String execExp = subExp_l;
                        while (m.find()) {
                            if ("()".equals(m.group()) || "(\"\")".equals(m.group())) {
                                execExp = execExp.replace(m.group(), "0");
                                continue;
                            }
                            String val = m.group().substring(1, m.group().length() - 1).replace("\"", "");
                            Long times = com.dhcc.sds.util.DateUtil.getTime(val);
                            int minutes = Math.toIntExact(times / divisor);
                            execExp = execExp.replace(val, String.valueOf(minutes));
                        }
                        triggerExp = triggerExp.replace(subExp_l, execExp);
                    }
                    triggerExp = triggerExp.replace(subExpStr_l, subExp_l);
                    triggerExp = triggerExp.replace(subExpType_l, "");
                }
            }
            triggerExp = triggerExp.replace(":", "");
            if (triggerExp.contains("contains")) {
                triggerExp = modifyExpression(triggerExp);
            }
            // 将表达式中的大括号中括号替换为小括号，以及其他其他字符替换为可执行字符
            triggerExp = triggerExp.replace("{", "(").replace("}", ")");
            triggerExp = triggerExp.replace("[", "(").replace("]", ")");
            triggerExp = triggerExp.replace("contains(\"\")", "contains(\",,\")");
            triggerExp = triggerExp.replace("oth", "OTH").replace("def", "DEF");

            // 运算前置条件表达式
            try {
                if ((boolean) engine.eval(triggerExp)) {
                    editPower = 1;
                }
            } catch (ScriptException e) {
                // 表达式解析失败，默认返回1
                return 1;
            }
        }
        return editPower;
    }

    public String modifyExpression(String expression) {
        String aExp = expression;

        //判断表达式中有无中括号
        if (!expression.matches(p2)) {
            if (!expression.contains("contains")) {
                return aExp;
            }
            // 循环处理原始表达式中的子表达式
            String[] subStrArr = aExp.split(".contains");
            for (int ExpInd = 0; ExpInd < subStrArr.length; ExpInd++) {
                String expSub = subStrArr[ExpInd];  // 提取子表达式
                // 提取引号内的内容
                String regExp = "(\").*?(\")";
                Pattern pattern = Pattern.compile(regExp);
                Matcher matcher = pattern.matcher(expSub);
                while (matcher.find()) {
                    String group = matcher.group();
                    String result = group.substring(1, group.length() - 1);
                    result = "\"," + result + ",\"";
                    aExp = aExp.replaceFirst(group, result);
                }
            }
        } else {
            // 查找规则公式中中括号以内的字符
            Pattern pat2 = Pattern.compile(p2);
            // 替换关联项目的值
            Matcher m2 = pat2.matcher(aExp);
            while (m2.find()) {
                String subGroup = m2.group();
                if (!subGroup.contains("contains")) {
                    continue;
                }
                String tmpGroup = subGroup;
                String tmpSubFroup = subGroup.substring(1, subGroup.length() - 1);
                // 循环处理原始表达式中的子表达式
                String[] subStrArr = tmpSubFroup.split(".contains");
                for (int ExpInd = 0; ExpInd < subStrArr.length; ExpInd++) {
                    String expSub = subStrArr[ExpInd];  // 提取子表达式
                    // 提取引号内的内容
                    String regExp = "(\").*?(\")";
                    Pattern pattern = Pattern.compile(regExp);
                    Matcher matcher = pattern.matcher(expSub);
                    while (matcher.find()) {
                        String group = matcher.group();
                        String result = group.substring(1, group.length() - 1);
                        result = "\"," + result + ",\"";
                        tmpGroup = tmpGroup.replaceFirst(group, result);
                    }
                }
                aExp = aExp.replace(subGroup, tmpGroup);
            }
        }

        return aExp;
    }

    /**
     * 转换日期格式(TYPE 1:XXXX年XX月XX日 TYPE 2:XXXXXXXX TYPE 3:XXXX年XX月 TYPE 4:XXXX年)
     *
     * @return str
     */
    public String getDateStr(String date, int type, int value) {
        String str = "";
        if ("".equals(date)) {
            return str;
        }
        switch (type) {
            case 1:
                str += date.substring(0, 4) + "年";
                str += date.substring(5, 7) + "月";
                str += date.substring(8, 10) + "日";
                break;
            case 2:
                str += date.substring(0, 4);
                str += date.substring(5, 7);
                str += date.substring(8, 10);
                break;
            case 3:
                str += date.substring(0, 4) + "年";
                str += date.substring(5, 7) + "月";
                break;
            case 4:
                if (0 == value) {
                    str += date.substring(0, 4) + "年";
                } else {
                    String year = date.substring(0, 4);
                    str += (Integer.valueOf(year) + value) + "年";
                }

                break;
            case 5:
                str += date.substring(0, 4) + "年";
                if (date.substring(5, 7).equals("01")) {
                    str += "第一季度";
                } else if (date.substring(5, 7).equals("04")) {
                    str += "第二季度";
                } else if (date.substring(5, 7).equals("07")) {
                    str += "第三季度";
                } else if (date.substring(5, 7).equals("10")) {
                    str += "第四季度";
                }
                break;
            default:
        }
        return str;
    }

    /**
     * 本地图片转换Base64的方法
     *
     * @param imgPath     
     */
    private String imageToBase64(String imgPath) {
        byte[] data = null;
        // 读取图片字节数组
        try {
            InputStream in = new FileInputStream(imgPath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 返回Base64编码过的字节数组字符串
        return EncodeUtil.encodeBase64(Objects.requireNonNull(data));
    }

    /**
     * 生成折现图
     *
     * @param chartName
     * @param dataSet
     * @throws Exception
     */
    private String drawLineChart(String chartName, CategoryDataset dataSet) {
        //图片保存路径
        String filePath = sysPro.getStaticPath() + "file_getReport/reportFiles/";
        //文件名称
        String fileName = filePath + chartName + ".png";
        //创建主题样式
        StandardChartTheme standardChartTheme = new StandardChartTheme("CN");
        //设置标题字体
        standardChartTheme.setExtraLargeFont(new Font("宋体", Font.BOLD, 20));
        //设置图例的字体
        standardChartTheme.setRegularFont(new Font("宋体", Font.PLAIN, 15));
        //设置轴向的字体
        standardChartTheme.setLargeFont(new Font("宋体", Font.PLAIN, 15));
        //应用主题样式
        ChartFactory.setChartTheme(standardChartTheme);

        JFreeChart chart = ChartFactory.createBarChart(
                null,//图名字
                "月份",//横坐标
                "数值",//纵坐标
                dataSet,//数据集
                PlotOrientation.VERTICAL,
                true, // 显示图例
                true, // 采用标准生成器
                false);// 是否生成超链接
        // 设置外层图片 无边框 无背景色 背景图片透明
        chart.setBorderVisible(false);
        chart.setBackgroundPaint(null);
        chart.setBackgroundImageAlpha(0.0f);
        CategoryPlot plot = (CategoryPlot) chart.getPlot();
        // 透明度
        plot.setForegroundAlpha(0.5f);
        // 背景全透明
        plot.setBackgroundAlpha(0.0f);
        // 去除背景边框线
        plot.setOutlinePaint(null);
        // X轴倾斜45度
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_45);

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(fileName);
            try {
                ChartUtilities.writeChartAsPNG(out, chart, 500, 350);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return fileName;
    }

    public static void generateImage(String base64, String path) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        try (OutputStream out = new FileOutputStream(path)) {
            // 解密
            byte[] b = decoder.decodeBuffer(base64);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {
                    b[i] += 256;
                }
            }
            out.write(b);
            out.flush();
        }
    }

    private String drawEChart(HashMap<String, Object> datas) throws IOException, TemplateException {
        String res = "";
        //模板路径
        String templatePath = sysPro.getStaticPath() + "file_getReport/";
        // 生成option字符串
        String option = FreemarkerUtil.generateString("option.ftl", templatePath, datas);
        // 根据option参数
        res = EchartsUtil.generateEchartsBase64(option);
        return res;
    }

    private String median(List<AnalysisSdsPortalVo> list) {
        String res = "";
        if (StringUtils.isEmpty(list)) {
            return res;
        } else {
            DecimalFormat df = new DecimalFormat("0.00");
            int size = list.size();
            if (size % 2 == 0) {
                String s1 = list.get(size / 2 - 1).getaRatio();
                BigDecimal dataA = new BigDecimal(s1);
                String s2 = list.get(size / 2).getaRatio();
                BigDecimal dataB = new BigDecimal(s2);
                BigDecimal sum = dataA.add(dataB);
                res = df.format(sum.divide(new BigDecimal(2)));
                res = res + "%";
            } else {
                res = list.get(size / 2).getaRatio() + "%";
            }
        }
        return res;
    }

}
